xref: /trunk/main/svtools/source/contnr/fileview.cxx (revision cdf0e10c)
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_svtools.hxx"
30 
31 #include <svtools/fileview.hxx>
32 #include <svtools/svtdata.hxx>
33 #include <svtools/imagemgr.hxx>
34 #include <svtools/headbar.hxx>
35 #include <svtools/svtabbx.hxx>
36 #include <svtools/svtools.hrc>
37 #include "fileview.hrc"
38 #include "contentenumeration.hxx"
39 #include <svtools/AccessibleBrowseBoxObjType.hxx>
40 #include <com/sun/star/util/DateTime.hpp>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <com/sun/star/task/XInteractionHandler.hpp>
43 #include <com/sun/star/ucb/XProgressHandler.hpp>
44 #include <com/sun/star/sdbc/XResultSet.hpp>
45 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
46 #include <com/sun/star/ucb/XContentAccess.hpp>
47 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
48 #include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp>
49 #include <com/sun/star/sdbc/XRow.hpp>
50 #include <com/sun/star/container/XChild.hpp>
51 #include <com/sun/star/ucb/CommandAbortedException.hpp>
52 #include <com/sun/star/ucb/ContentCreationException.hpp>
53 #include <vcl/waitobj.hxx>
54 #include <com/sun/star/io/XPersist.hpp>
55 #include <com/sun/star/beans/XPropertySet.hpp>
56 #include <com/sun/star/ucb/XCommandInfo.hpp>
57 #include <com/sun/star/beans/XPropertySetInfo.hpp>
58 #include <com/sun/star/beans/PropertyAttribute.hpp>
59 
60 #include <algorithm>
61 #include <memory>
62 #include <tools/urlobj.hxx>
63 #include <tools/datetime.hxx>
64 #include <comphelper/processfactory.hxx>
65 #include <unotools/localfilehelper.hxx>
66 #include <ucbhelper/content.hxx>
67 #include <ucbhelper/commandenvironment.hxx>
68 #include <vcl/msgbox.hxx>
69 #ifndef INCLUDED_RTL_MATH_H
70 #include <rtl/math.hxx>
71 #endif
72 #include <tools/config.hxx>
73 #include <osl/mutex.hxx>
74 #include <osl/conditn.hxx>
75 #include <vos/timer.hxx>
76 #include <vcl/svapp.hxx>
77 #include <vcl/sound.hxx>
78 #include <unotools/ucbhelper.hxx>
79 #include <unotools/intlwrapper.hxx>
80 #include <unotools/syslocale.hxx>
81 #include <svl/urlfilter.hxx>
82 
83 using namespace ::com::sun::star::lang;
84 using namespace ::com::sun::star::sdbc;
85 using namespace ::com::sun::star::task;
86 using namespace ::com::sun::star::ucb;
87 using namespace ::com::sun::star::uno;
88 using namespace ::com::sun::star::io;
89 using namespace ::com::sun::star::beans;
90 using namespace ::comphelper;
91 using ::svt::SortingData_Impl;
92 using ::svt::FolderDescriptor;
93 using ::vos::TTimeValue;
94 using ::rtl::OUString;
95 
96 #define ALL_FILES_FILTER    "*.*"
97 
98 #define COLUMN_TITLE        1
99 #define COLUMN_TYPE         2
100 #define COLUMN_SIZE         3
101 #define COLUMN_DATE         4
102 
103 DECLARE_LIST( StringList_Impl, OUString* )
104 
105 #define ROW_HEIGHT                17    // the height of a row has to be a little higher than the bitmap
106 #define QUICK_SEARCH_TIMEOUT    1500    // time in mSec before the quicksearch string will be reseted
107 
108 namespace
109 {
110     //====================================================================
111     //= ReleaseSolarMutex
112     //====================================================================
113     struct ReleaseSolarMutex
114     {
115     private:
116         sal_uLong   m_nCount;
117 
118     public:
119         inline ReleaseSolarMutex()
120         {
121             m_nCount = Application::ReleaseSolarMutex();
122         }
123         inline ~ReleaseSolarMutex()
124         {
125             Application::AcquireSolarMutex( m_nCount );
126         }
127     };
128 
129     //====================================================================
130     //= ITimeoutHandler
131     //====================================================================
132     class CallbackTimer;
133     class ITimeoutHandler
134     {
135     public:
136         virtual void onTimeout( CallbackTimer* _pInstigator ) = 0;
137     };
138 
139     //====================================================================
140     //= CallbackTimer
141     //====================================================================
142     class CallbackTimer : public ::vos::OTimer
143     {
144     protected:
145         ITimeoutHandler* m_pTimeoutHandler;
146 
147     public:
148         CallbackTimer( ITimeoutHandler* _pHandler ) : m_pTimeoutHandler( _pHandler ) { }
149 
150     protected:
151         virtual void SAL_CALL onShot();
152     };
153 
154     //--------------------------------------------------------------------
155     void SAL_CALL CallbackTimer::onShot()
156     {
157         OSL_ENSURE( m_pTimeoutHandler, "CallbackTimer::onShot: nobody interested in?" );
158         ITimeoutHandler* pHandler( m_pTimeoutHandler );
159         if ( pHandler )
160             pHandler->onTimeout( this );
161     }
162 
163 }
164 
165 // -----------------------------------------------------------------------
166 
167 static sal_Bool isHighContrast( const Window* _pView )
168 {
169     return _pView->GetSettings().GetStyleSettings().GetHighContrastMode();
170 }
171 
172 // -----------------------------------------------------------------------
173 
174 void FilterMatch::createWildCardFilterList(const String& _rFilterList,::std::vector< WildCard >& _rFilters)
175 {
176     if( _rFilterList.Len() )
177     {// filter is given
178         xub_StrLen nCount = _rFilterList.GetTokenCount();
179         _rFilters.reserve( nCount );
180         xub_StrLen nIndex = 0;
181         OUString sToken;
182         do
183         {
184             sToken = _rFilterList.GetToken( 0, ';', nIndex );
185             if ( sToken.getLength() )
186             {
187                 _rFilters.push_back( WildCard( sToken.toAsciiUpperCase() ) );
188             }
189         }
190         while ( nIndex != STRING_NOTFOUND );
191     }
192     else
193         // no filter is given -> match all
194         _rFilters.push_back( WildCard( String::CreateFromAscii( "*" ) ) );
195 }
196 // class ViewTabListBox_Impl ---------------------------------------------
197 
198 class ViewTabListBox_Impl : public SvHeaderTabListBox
199 {
200 private:
201     Reference< XCommandEnvironment >    mxCmdEnv;
202 
203     ::osl::Mutex            maMutex;
204     HeaderBar*              mpHeaderBar;
205     SvtFileView_Impl*       mpParent;
206     Timer                   maResetQuickSearch;
207     OUString                maQuickSearchText;
208     String                  msAccessibleDescText;
209     String                  msFolder;
210     String                  msFile;
211     sal_uInt32              mnSearchIndex;
212     sal_Bool                mbResizeDisabled        : 1;
213     sal_Bool                mbAutoResize            : 1;
214     sal_Bool                mbEnableDelete          : 1;
215     sal_Bool                mbEnableRename          : 1;
216 
217     void            DeleteEntries();
218     void            DoQuickSearch( const xub_Unicode& rChar );
219     sal_Bool        Kill( const OUString& rURL );
220 
221 protected:
222     virtual sal_Bool            DoubleClickHdl();
223     virtual ::rtl::OUString GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const;
224 
225 public:
226     ViewTabListBox_Impl( Window* pParentWin, SvtFileView_Impl* pParent, sal_Int16 nFlags );
227    ~ViewTabListBox_Impl();
228 
229     virtual void    Resize();
230     virtual void    KeyInput( const KeyEvent& rKEvt );
231     virtual sal_Bool    EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText );
232 
233     void            ClearAll();
234     HeaderBar*      GetHeaderBar() const { return mpHeaderBar; }
235 
236     void            EnableAutoResize() { mbAutoResize = sal_True; }
237     void            EnableDelete( sal_Bool bEnable ) { mbEnableDelete = bEnable; }
238     void            EnableRename( sal_Bool bEnable ) { mbEnableRename = bEnable; }
239     sal_Bool        IsDeleteOrContextMenuEnabled() { return mbEnableDelete || IsContextMenuHandlingEnabled(); }
240 
241     Reference< XCommandEnvironment >    GetCommandEnvironment() const { return mxCmdEnv; }
242 
243     DECL_LINK( ResetQuickSearch_Impl, Timer * );
244 
245     virtual PopupMenu*  CreateContextMenu( void );
246     virtual void        ExcecuteContextMenuAction( sal_uInt16 nSelectedPopentry );
247 };
248 
249 // class HashedEntry --------------------------------------------------
250 
251 class HashedEntry
252 {   // just a special String which can be compared on equality much faster
253 protected:
254     OUString                maName;
255     sal_Int32               mnHashCode;
256 public:
257     inline                  HashedEntry( const OUString& rName );
258     inline                  HashedEntry( const INetURLObject& rURL );
259     inline                  HashedEntry( const HashedEntry& rCopy );
260     virtual                 ~HashedEntry();
261 
262     inline sal_Bool operator    ==( const HashedEntry& rRef ) const;
263     inline sal_Bool operator    !=( const HashedEntry& rRef ) const;
264 
265     inline const OUString&  GetName() const;
266 };
267 
268 inline HashedEntry::HashedEntry( const OUString& rName ): maName( rName ), mnHashCode( rName.hashCode() )
269 {
270 }
271 
272 inline HashedEntry::HashedEntry( const INetURLObject& rURL ):
273     maName( rURL.GetMainURL( INetURLObject::NO_DECODE ) ),
274     mnHashCode( maName.hashCode() )
275 {
276 }
277 
278 inline HashedEntry::HashedEntry( const HashedEntry& r ): maName( r.maName ), mnHashCode( r.mnHashCode )
279 {
280 }
281 
282 HashedEntry::~HashedEntry()
283 {
284 }
285 
286 inline sal_Bool HashedEntry::operator ==( const HashedEntry& rRef ) const
287 {
288     return mnHashCode == rRef.mnHashCode && maName.reverseCompareTo( rRef.maName ) == 0;
289 }
290 
291 inline sal_Bool HashedEntry::operator !=( const HashedEntry& rRef ) const
292 {
293     return mnHashCode != rRef.mnHashCode || maName.reverseCompareTo( rRef.maName ) != 0;
294 }
295 
296 inline const OUString& HashedEntry::GetName() const
297 {
298     return maName;
299 }
300 
301 // class HashedEntryList ----------------------------------------------
302 
303 class HashedEntryList : protected List
304 {// provides a list of _unique_ Entries
305 protected:
306     inline HashedEntry*         First();
307     inline HashedEntry*         Next();
308     inline void                 Append( HashedEntry* pNewEntry );
309 public:
310     virtual                     ~HashedEntryList();
311 
312     const HashedEntry*      Find( const OUString& rNameToSearchFor );
313     const HashedEntry*      Find( const HashedEntry& rToSearchFor );
314                                 // not const, because First()/Next() is used
315     using List::Insert;
316     const HashedEntry&      Insert( HashedEntry* pInsertOrDelete );
317                                 // don't care about pInsertOrDelete after this any more and handle it as invalid!
318                                 // returns the Entry, which is effectively inserted
319 
320     void                    Clear();
321 };
322 
323 inline HashedEntry* HashedEntryList::First()
324 {
325     return ( HashedEntry* ) List::First();
326 }
327 
328 inline HashedEntry* HashedEntryList::Next()
329 {
330     return ( HashedEntry* ) List::Next();
331 }
332 
333 inline void HashedEntryList::Append( HashedEntry* pNew )
334 {
335     List::Insert( pNew, LIST_APPEND );
336 }
337 
338 HashedEntryList::~HashedEntryList()
339 {
340     Clear();
341 }
342 
343 const HashedEntry* HashedEntryList::Find( const OUString& rRefName )
344 {   // simple linear search, which should be fast enough for this purpose
345     HashedEntry  aRef( rRefName );
346     HashedEntry* pIter = First();
347     while( pIter && *pIter != aRef )
348         pIter = Next();
349 
350     return pIter;
351 }
352 
353 const HashedEntry* HashedEntryList::Find( const HashedEntry& rRef )
354 {   // simple linear search, which should be fast enough for this purpose
355     HashedEntry* pIter = First();
356     while( pIter && *pIter != rRef )
357         pIter = Next();
358 
359     return pIter;
360 }
361 
362 const HashedEntry& HashedEntryList::Insert( HashedEntry* pNew )
363 {   // inserts (appends) only, if entry doesn't already exists
364     // if it already exists, pNew is deleted, because the caller must not worry about pNew any more
365 
366     DBG_ASSERT( pNew, "HashedEntryList::Insert(): NULL-pointer can't be inserted" );
367 
368     const HashedEntry* pSearch = Find( *pNew );
369     if( pSearch )
370     {
371         delete pNew;
372         return *pSearch;
373     }
374 
375     Append( pNew );
376 
377     return *pNew;
378 }
379 
380 void HashedEntryList::Clear()
381 {
382     HashedEntry* p = First();
383     while( p )
384     {
385         delete p;
386         p = Next();
387     }
388 }
389 
390 // class NameTranslationEntry -----------------------------------------
391 
392 class NameTranslationEntry : public HashedEntry
393 {// a fast compareble String and another String, which is used to get a substitution for a given String
394 protected:
395     OUString                maTranslatedName;
396 public:
397     inline                  NameTranslationEntry( const OUString& rOriginalName, const OUString& rTranslatedName );
398     inline                  NameTranslationEntry( const ByteString& rOriginalName, const ByteString& rTranslatedName );
399 
400     inline const OUString&  GetTranslation() const;
401 };
402 
403 inline NameTranslationEntry::NameTranslationEntry( const OUString& rOrg, const OUString& rTrans ):
404     HashedEntry( rOrg ),
405     maTranslatedName( rTrans )
406 {
407 }
408 
409 inline NameTranslationEntry::NameTranslationEntry( const ByteString& rOrg, const ByteString& rTrans ):
410     HashedEntry( OUString( rOrg.GetBuffer(), rOrg.Len(), RTL_TEXTENCODING_ASCII_US ) ),
411     maTranslatedName( OUString( rTrans.GetBuffer(), rTrans.Len(), RTL_TEXTENCODING_UTF8 ) )
412 {
413 }
414 
415 inline const OUString& NameTranslationEntry::GetTranslation() const
416 {
417     return maTranslatedName;
418 }
419 
420 // class NameTranslationList -----------------------------------------
421 
422 class NameTranslationList : protected HashedEntryList
423 {   // contains a list of substitutes of strings for a given folder (as URL)
424     // explanation of the circumstances see in remarks for Init();
425 protected:
426     INetURLObject               maTransFile;    // URL of file with translation entries
427     HashedEntry                 maHashedURL;    // for future purposes when dealing with a set of cached
428                                                 //  NameTranslationLists
429 private:
430     const String            maTransFileName;
431     void                    Init();             // reads the translation file and fills the (internal) list
432 
433 public:
434                             NameTranslationList( const INetURLObject& rBaseURL );
435                                             // rBaseURL: path to folder for which the translation of the entries
436                                             //  should be done
437 
438     using List::operator==;
439     inline sal_Bool operator    ==( const HashedEntry& rRef ) const;
440     using List::operator!=;
441     inline sal_Bool operator    !=( const HashedEntry& rRef ) const;
442 
443     const OUString*             Translate( const OUString& rName ) const;
444                                             // returns NULL, if rName can't be found
445 
446     inline void                 Update();   // clears list and init
447 
448     inline const String&        GetTransTableFileName() const;
449                                             // returns the name for the file, which contains the translation strings
450 };
451 
452 inline const String& NameTranslationList::GetTransTableFileName() const
453 {
454     return maTransFileName;
455 }
456 
457 void NameTranslationList::Init()
458 {
459 // Tries to read the file ".nametranslation.table" in the base folder. Complete path/name is in maTransFile.
460 // Further on, the found entries in the section "TRANSLATIONNAMES" are used to replace names in the
461 // base folder by translated ones. The translation must be given in UTF8
462 // See examples of such a files in the samples-folder of an Office installation
463 
464     try
465     {
466         ::ucbhelper::Content aTestContent( maTransFile.GetMainURL( INetURLObject::NO_DECODE ), Reference< XCommandEnvironment >() );
467 
468         if( aTestContent.isDocument() )
469         {// ... also tests the existence of maTransFile by throwing an Exception
470             const sal_Char*     pSection = "TRANSLATIONNAMES";
471             String          aFsysName( maTransFile.getFSysPath( INetURLObject::FSYS_DETECT ) );
472             Config          aConfig( aFsysName );
473 
474             aConfig.SetGroup( ByteString( pSection ) );
475 
476             sal_uInt16          nKeyCnt = aConfig.GetKeyCount();
477 
478             for( sal_uInt16 nCnt = 0 ; nCnt < nKeyCnt ; ++nCnt )
479                 Insert( new NameTranslationEntry( aConfig.GetKeyName( nCnt ), aConfig.ReadKey( nCnt ) ) );
480         }
481     }
482     catch( Exception const & ) {}
483 }
484 
485 NameTranslationList::NameTranslationList( const INetURLObject& rBaseURL ):
486     maTransFile( rBaseURL ),
487     maHashedURL( rBaseURL ),
488     maTransFileName( String::CreateFromAscii( ".nametranslation.table" ) )
489 {
490     maTransFile.insertName( maTransFileName );
491     Init();
492 }
493 
494 inline sal_Bool NameTranslationList::operator ==( const HashedEntry& rRef ) const
495 {
496     return maHashedURL == rRef;
497 }
498 
499 inline sal_Bool NameTranslationList::operator !=( const HashedEntry& rRef ) const
500 {
501     return maHashedURL != rRef;
502 }
503 
504 const OUString* NameTranslationList::Translate( const OUString& rName ) const
505 {
506     const NameTranslationEntry* pSearch = static_cast< const NameTranslationEntry* >(
507                                         ( const_cast< NameTranslationList* >( this ) )->Find( rName ) );
508 
509     return pSearch? &pSearch->GetTranslation() : NULL;
510 }
511 
512 inline void NameTranslationList::Update()
513 {
514     Clear();
515     Init();
516 }
517 
518 // class NameTranslator_Impl ------------------------------------------
519 
520 // enables the user to get string substitutions (translations for the content) for a given folder
521 // see more explanations above in the description for NameTranslationList
522 class NameTranslator_Impl : public ::svt::IContentTitleTranslation
523 {
524 private:
525     NameTranslationList*    mpActFolder;
526 public:
527                             NameTranslator_Impl( void );
528                             NameTranslator_Impl( const INetURLObject& rActualFolder );
529                             virtual ~NameTranslator_Impl();
530 
531      // IContentTitleTranslation
532     virtual sal_Bool        GetTranslation( const OUString& rOriginalName, OUString& rTranslatedName ) const;
533 
534     void                    UpdateTranslationTable(); // reads the translation file again
535 
536     void                    SetActualFolder( const INetURLObject& rActualFolder );
537     const String*           GetTransTableFileName() const;
538                                             // returns the name for the file, which contains the translation strings
539 };
540 
541 //====================================================================
542 //= SvtFileView_Impl
543 //====================================================================
544 
545 class SvtFileView_Impl  :public ::svt::IEnumerationResultHandler
546                         ,public ITimeoutHandler
547 {
548 protected:
549     SvtFileView*                mpAntiImpl;
550     Link                        m_aSelectHandler;
551 
552     ::rtl::Reference< ::svt::FileViewContentEnumerator >
553                                         m_pContentEnumerator;
554     Link                                m_aCurrentAsyncActionHandler;
555     ::osl::Condition                    m_aAsyncActionFinished;
556     ::rtl::Reference< ::vos::OTimer >   m_pCancelAsyncTimer;
557     ::svt::EnumerationResult            m_eAsyncActionResult;
558     bool                                m_bRunningAsyncAction;
559     bool                                m_bAsyncActionCancelled;
560 
561 
562 public:
563 
564     ::std::vector< SortingData_Impl* >  maContent;
565     ::osl::Mutex                        maMutex;
566 
567     ViewTabListBox_Impl*    mpView;
568     NameTranslator_Impl*    mpNameTrans;
569     const IUrlFilter*       mpUrlFilter;
570     sal_uInt16              mnSortColumn;
571     sal_Bool                mbAscending     : 1;
572     sal_Bool                mbOnlyFolder    : 1;
573     sal_Bool                mbReplaceNames  : 1;    // translate folder names or display doc-title instead of file name
574     sal_Int16               mnSuspendSelectCallback : 1;
575     sal_Bool                mbIsFirstResort : 1;
576 
577     IntlWrapper             aIntlWrapper;
578 
579     String                  maViewURL;
580     String                  maAllFilter;
581     String                  maCurrentFilter;
582     Image                   maFolderImage;
583     Link                    maOpenDoneLink;
584     Reference< XCommandEnvironment >    mxCmdEnv;
585 
586     SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv,
587                                               sal_Int16 nFlags,
588                                               sal_Bool bOnlyFolder );
589     virtual                ~SvtFileView_Impl();
590 
591     void                    Clear();
592 
593     FileViewResult          GetFolderContent_Impl(
594         const String& rFolder,
595         const FileViewAsyncAction* pAsyncDescriptor,
596         const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >() );
597 
598     FileViewResult          GetFolderContent_Impl(
599         const FolderDescriptor& _rFolder,
600         const FileViewAsyncAction* pAsyncDescriptor,
601         const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList = ::com::sun::star::uno::Sequence< ::rtl::OUString >());
602     void                    FilterFolderContent_Impl( const OUString &rFilter );
603     void                    CancelRunningAsyncAction();
604 
605     void                    OpenFolder_Impl();
606     // #83004# -------
607     void                        ReplaceTabWithString( OUString& aValue );
608     void                    CreateDisplayText_Impl();
609     void                    CreateVector_Impl( const Sequence < OUString > &rList );
610     void                    SortFolderContent_Impl();
611 
612     void                    EntryRemoved( const OUString& rURL );
613     void                    EntryRenamed( OUString& rURL,
614                                           const OUString& rName );
615     String                  FolderInserted( const OUString& rURL,
616                                             const OUString& rTitle );
617 
618     sal_uLong                   GetEntryPos( const OUString& rURL );
619 
620     inline void             EnableContextMenu( sal_Bool bEnable );
621     inline void             EnableDelete( sal_Bool bEnable );
622 
623     void                    Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending );
624     sal_Bool                SearchNextEntry( sal_uInt32 &nIndex,
625                                              const OUString& rTitle,
626                                              sal_Bool bWrapAround );
627 
628     inline sal_Bool         EnableNameReplacing( sal_Bool bEnable = sal_True ); // returns false, if action wasn't possible
629     void                    SetActualFolder( const INetURLObject& rActualFolder );
630 
631     sal_Bool                GetDocTitle( const OUString& rTargetURL, OUString& rDocTitle ) const;
632 
633     void                    SetSelectHandler( const Link& _rHdl );
634 
635     void                    InitSelection();
636     void                    ResetCursor();
637 
638     inline void             EndEditing( bool _bCancel );
639 
640 protected:
641     DECL_LINK( SelectionMultiplexer, void* );
642 
643 protected:
644     // IEnumerationResultHandler overridables
645     virtual void        enumerationDone( ::svt::EnumerationResult _eResult );
646             void        implEnumerationSuccess();
647 
648     // ITimeoutHandler
649     virtual void onTimeout( CallbackTimer* _pInstigator );
650 };
651 
652 inline void SvtFileView_Impl::EnableContextMenu( sal_Bool bEnable )
653 {
654     mpView->EnableContextMenuHandling( bEnable );
655     if( bEnable )
656         mbReplaceNames = sal_False;
657 }
658 
659 inline void SvtFileView_Impl::EnableDelete( sal_Bool bEnable )
660 {
661     mpView->EnableDelete( bEnable );
662     if( bEnable )
663         mbReplaceNames = sal_False;
664 }
665 
666 inline sal_Bool SvtFileView_Impl::EnableNameReplacing( sal_Bool bEnable )
667 {
668     mpView->EnableRename( bEnable );
669 
670     sal_Bool bRet;
671     if( mpView->IsDeleteOrContextMenuEnabled() )
672     {
673         DBG_ASSERT( !mbReplaceNames, "SvtFileView_Impl::EnableNameReplacing(): state should be not possible!" );
674         bRet = !bEnable; // only for enabling this is an unsuccessful result
675     }
676     else
677     {
678         mbReplaceNames = bEnable;
679         bRet = sal_True;
680     }
681 
682     return bRet;
683 }
684 
685 inline void SvtFileView_Impl::EndEditing( bool _bCancel )
686 {
687     if ( mpView->IsEditingActive() )
688         mpView->EndEditing( _bCancel != false );
689 }
690 
691 // functions -------------------------------------------------------------
692 
693 OUString CreateExactSizeText_Impl( sal_Int64 nSize )
694 {
695     double fSize( ( double ) nSize );
696     int nDec;
697 
698     long nMega = 1024 * 1024;
699     long nGiga = nMega * 1024;
700 
701     String aUnitStr = ' ';
702 
703     if ( nSize < 10000 )
704     {
705         aUnitStr += String( SvtResId( STR_SVT_BYTES ) );
706         nDec = 0;
707     }
708     else if ( nSize < nMega )
709     {
710         fSize /= 1024;
711         aUnitStr += String( SvtResId( STR_SVT_KB ) );
712         nDec = 1;
713     }
714     else if ( nSize < nGiga )
715     {
716         fSize /= nMega;
717         aUnitStr += String( SvtResId( STR_SVT_MB ) );
718         nDec = 2;
719     }
720     else
721     {
722         fSize /= nGiga;
723         aUnitStr += String( SvtResId( STR_SVT_GB ) );
724         nDec = 3;
725     }
726 
727     OUString aSizeStr( ::rtl::math::doubleToUString( fSize,
728                 rtl_math_StringFormat_F, nDec,
729                 SvtSysLocale().GetLocaleData().getNumDecimalSep().GetChar(0)));
730     aSizeStr += aUnitStr;
731 
732     return aSizeStr;
733 }
734 
735 // -----------------------------------------------------------------------
736 // class ViewTabListBox_Impl ---------------------------------------------
737 // -----------------------------------------------------------------------
738 
739 ViewTabListBox_Impl::ViewTabListBox_Impl( Window* pParentWin,
740                                           SvtFileView_Impl* pParent,
741                                           sal_Int16 nFlags ) :
742 
743     SvHeaderTabListBox( pParentWin, WB_TABSTOP ),
744 
745     mpHeaderBar         ( NULL ),
746     mpParent            ( pParent ),
747     msAccessibleDescText( SvtResId( STR_SVT_ACC_DESC_FILEVIEW ) ),
748     msFolder            ( SvtResId( STR_SVT_ACC_DESC_FOLDER ) ),
749     msFile              ( SvtResId( STR_SVT_ACC_DESC_FILE ) ),
750     mnSearchIndex       ( 0 ),
751     mbResizeDisabled    ( sal_False ),
752     mbAutoResize        ( sal_False ),
753     mbEnableDelete      ( sal_True ),
754     mbEnableRename      ( sal_True )
755 
756 {
757     Size aBoxSize = pParentWin->GetSizePixel();
758     mpHeaderBar = new HeaderBar( pParentWin, WB_BUTTONSTYLE | WB_BOTTOMBORDER );
759     mpHeaderBar->SetPosSizePixel( Point( 0, 0 ), mpHeaderBar->CalcWindowSizePixel() );
760 
761     HeaderBarItemBits nBits = ( HIB_LEFT | HIB_VCENTER | HIB_CLICKABLE );
762     if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL )
763     {
764         mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 180, nBits | HIB_UPARROW );
765         mpHeaderBar->InsertItem( COLUMN_TYPE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TYPE ) ), 140, nBits );
766         mpHeaderBar->InsertItem( COLUMN_SIZE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_SIZE ) ), 80, nBits );
767         mpHeaderBar->InsertItem( COLUMN_DATE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_DATE ) ), 500, nBits );
768     }
769     else
770         mpHeaderBar->InsertItem( COLUMN_TITLE, String( SvtResId( STR_SVT_FILEVIEW_COLUMN_TITLE ) ), 600, nBits );
771 
772     Size aHeadSize = mpHeaderBar->GetSizePixel();
773     SetPosSizePixel( Point( 0, aHeadSize.Height() ),
774                      Size( aBoxSize.Width(), aBoxSize.Height() - aHeadSize.Height() ) );
775     InitHeaderBar( mpHeaderBar );
776     SetHighlightRange();
777     SetEntryHeight( ROW_HEIGHT );
778 
779     Show();
780     mpHeaderBar->Show();
781 
782     maResetQuickSearch.SetTimeout( QUICK_SEARCH_TIMEOUT );
783     maResetQuickSearch.SetTimeoutHdl( LINK( this, ViewTabListBox_Impl, ResetQuickSearch_Impl ) );
784 
785     Reference< XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
786     Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
787                xFactory->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
788 
789     mxCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
790 
791     EnableContextMenuHandling();
792 }
793 
794 // -----------------------------------------------------------------------
795 
796 ViewTabListBox_Impl::~ViewTabListBox_Impl()
797 {
798     maResetQuickSearch.Stop();
799 
800     delete mpHeaderBar;
801 }
802 
803 // -----------------------------------------------------------------------
804 
805 IMPL_LINK( ViewTabListBox_Impl, ResetQuickSearch_Impl, Timer*, EMPTYARG )
806 {
807     ::osl::MutexGuard aGuard( maMutex );
808 
809     maQuickSearchText = OUString();
810     mnSearchIndex = 0;
811 
812     return 0;
813 }
814 
815 // -----------------------------------------------------------------------
816 
817 void ViewTabListBox_Impl::Resize()
818 {
819     SvTabListBox::Resize();
820     Size aBoxSize = Control::GetParent()->GetOutputSizePixel();
821 
822     if ( mbResizeDisabled || !aBoxSize.Width() )
823         return;
824 
825     Size aBarSize = mpHeaderBar->GetSizePixel();
826     aBarSize.Width() = mbAutoResize ? aBoxSize.Width() : GetSizePixel().Width();
827     mpHeaderBar->SetSizePixel( aBarSize );
828 
829     if ( mbAutoResize )
830     {
831         mbResizeDisabled = sal_True;
832         Point aPos = GetPosPixel();
833         SetPosSizePixel( Point( 0, aBarSize.Height() ),
834                         Size( aBoxSize.Width(), aBoxSize.Height() - aBarSize.Height() ) );
835         mbResizeDisabled = sal_False;
836     }
837 }
838 
839 // -----------------------------------------------------------------------
840 
841 void ViewTabListBox_Impl::KeyInput( const KeyEvent& rKEvt )
842 {
843     bool bHandled = false;
844 
845     const KeyCode& rKeyCode = rKEvt.GetKeyCode();
846     if ( 0 == rKeyCode.GetModifier() )
847     {
848         if ( rKeyCode.GetCode() == KEY_RETURN )
849         {
850             ResetQuickSearch_Impl( NULL );
851             GetDoubleClickHdl().Call( this );
852             bHandled = true;
853         }
854         else if ( ( rKeyCode.GetCode() == KEY_DELETE ) &&
855                   mbEnableDelete )
856         {
857             ResetQuickSearch_Impl( NULL );
858             DeleteEntries();
859             bHandled = true;
860         }
861         else if ( ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_NUM ) ||
862                   ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_ALPHA ) )
863         {
864             DoQuickSearch( rKEvt.GetCharCode() );
865             bHandled = true;
866         }
867     }
868 
869     if ( !bHandled )
870     {
871         ResetQuickSearch_Impl( NULL );
872         SvHeaderTabListBox::KeyInput( rKEvt );
873     }
874 }
875 
876 // -----------------------------------------------------------------------
877 
878 PopupMenu* ViewTabListBox_Impl::CreateContextMenu( void )
879 {
880     bool bEnableDelete = mbEnableDelete;
881     bool bEnableRename = mbEnableRename;
882 
883     if ( bEnableDelete || bEnableRename )
884     {
885         sal_Int32 nSelectedEntries = GetSelectionCount();
886         bEnableDelete &= nSelectedEntries > 0;
887         bEnableRename &= nSelectedEntries == 1;
888     }
889 
890     if ( bEnableDelete || bEnableRename )
891     {
892         SvLBoxEntry* pEntry = FirstSelected();
893         while ( pEntry )
894         {
895             ::ucbhelper::Content aCnt;
896             try
897             {
898                 OUString aURL( static_cast< SvtContentEntry * >(
899                     pEntry->GetUserData() )->maURL );
900                 aCnt = ::ucbhelper::Content( aURL, mxCmdEnv );
901             }
902             catch( Exception const & )
903             {
904                 bEnableDelete = bEnableRename = false;
905             }
906 
907             if ( bEnableDelete )
908             {
909                 try
910                 {
911                     Reference< XCommandInfo > aCommands = aCnt.getCommands();
912                     if ( aCommands.is() )
913                         bEnableDelete
914                             = aCommands->hasCommandByName(
915                                 OUString::createFromAscii( "delete" ) );
916                     else
917                         bEnableDelete = false;
918                 }
919                 catch( Exception const & )
920                 {
921                     bEnableDelete = false;
922                 }
923             }
924 
925             if ( bEnableRename )
926             {
927                 try
928                 {
929                     Reference< XPropertySetInfo > aProps = aCnt.getProperties();
930                     if ( aProps.is() )
931                     {
932                         Property aProp
933                             = aProps->getPropertyByName(
934                                 OUString::createFromAscii( "Title" ) );
935                         bEnableRename
936                             = !( aProp.Attributes & PropertyAttribute::READONLY );
937                     }
938                     else
939                         bEnableRename = false;
940                 }
941                 catch( Exception const & )
942                 {
943                     bEnableRename = false;
944                 }
945             }
946 
947             pEntry = ( bEnableDelete || bEnableRename )
948                 ? NextSelected( pEntry )
949                 : 0;
950         }
951     }
952 
953     if ( bEnableDelete || bEnableRename )
954     {
955         PopupMenu * pRet
956             = new PopupMenu( SvtResId( RID_FILEVIEW_CONTEXTMENU ) );
957         pRet->EnableItem( MID_FILEVIEW_DELETE, bEnableDelete );
958         pRet->EnableItem( MID_FILEVIEW_RENAME, bEnableRename );
959         pRet->RemoveDisabledEntries( sal_True, sal_True );
960         return pRet;
961     }
962 
963     return NULL;
964 }
965 
966 // -----------------------------------------------------------------------
967 
968 void ViewTabListBox_Impl::ExcecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry )
969 {
970     switch ( nSelectedPopupEntry )
971     {
972         case MID_FILEVIEW_DELETE :
973             DeleteEntries();
974             break;
975 
976         case MID_FILEVIEW_RENAME :
977             EditEntry( FirstSelected() );
978             break;
979     }
980 }
981 
982 // -----------------------------------------------------------------------
983 
984 void ViewTabListBox_Impl::ClearAll()
985 {
986     for ( sal_uInt16 i = 0; i < GetEntryCount(); ++i )
987         delete (SvtContentEntry*)GetEntry(i)->GetUserData();
988     Clear();
989 }
990 
991 // -----------------------------------------------------------------------
992 void ViewTabListBox_Impl::DeleteEntries()
993 {
994     svtools::QueryDeleteResult_Impl eResult = svtools::QUERYDELETE_YES;
995     SvLBoxEntry* pEntry = FirstSelected();
996     String aURL;
997 
998     ByteString sDialogPosition;
999     while ( pEntry && ( eResult != svtools::QUERYDELETE_CANCEL ) )
1000     {
1001         SvLBoxEntry *pCurEntry = pEntry;
1002         pEntry = NextSelected( pEntry );
1003 
1004         if ( pCurEntry->GetUserData() )
1005             aURL = ( (SvtContentEntry*)pCurEntry->GetUserData() )->maURL;
1006 
1007         if ( !aURL.Len() )
1008             continue;
1009 
1010         bool canDelete = true;
1011         try
1012         {
1013             ::ucbhelper::Content aCnt( aURL, mxCmdEnv );
1014             Reference< XCommandInfo > aCommands = aCnt.getCommands();
1015             if ( aCommands.is() )
1016                 canDelete
1017                     = aCommands->hasCommandByName(
1018                         OUString::createFromAscii( "delete" ) );
1019             else
1020                 canDelete = false;
1021         }
1022         catch( Exception const & )
1023         {
1024             canDelete = false;
1025         }
1026 
1027         if (!canDelete)
1028             continue; // process next entry
1029 
1030         if ( eResult != svtools::QUERYDELETE_ALL )
1031         {
1032             INetURLObject aObj( aURL );
1033             svtools::QueryDeleteDlg_Impl aDlg( NULL, aObj.GetName( INetURLObject::DECODE_WITH_CHARSET ) );
1034             if ( sDialogPosition.Len() )
1035                 aDlg.SetWindowState( sDialogPosition );
1036 
1037             if ( GetSelectionCount() > 1 )
1038                 aDlg.EnableAllButton();
1039 
1040             if ( aDlg.Execute() == RET_OK )
1041                 eResult = aDlg.GetResult();
1042             else
1043                 eResult = svtools::QUERYDELETE_CANCEL;
1044 
1045             sDialogPosition = aDlg.GetWindowState( );
1046         }
1047 
1048         if ( ( eResult == svtools::QUERYDELETE_ALL ) ||
1049              ( eResult == svtools::QUERYDELETE_YES ) )
1050         {
1051             if ( Kill( aURL ) )
1052             {
1053                 delete (SvtContentEntry*)pCurEntry->GetUserData();
1054                 GetModel()->Remove( pCurEntry );
1055                 mpParent->EntryRemoved( aURL );
1056             }
1057         }
1058     }
1059 }
1060 
1061 // -----------------------------------------------------------------------
1062 sal_Bool ViewTabListBox_Impl::EditedEntry( SvLBoxEntry* pEntry,
1063                                  const XubString& rNewText )
1064 {
1065     sal_Bool bRet = sal_False;
1066 
1067     OUString aURL;
1068     SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData();
1069 
1070     if ( pData )
1071         aURL = OUString( pData->maURL );
1072 
1073     if ( ! aURL.getLength() )
1074         return bRet;
1075 
1076     try
1077     {
1078         OUString aPropName = OUString::createFromAscii( "Title" );
1079         bool canRename = true;
1080         ::ucbhelper::Content aContent( aURL, mxCmdEnv );
1081 
1082         try
1083         {
1084             Reference< XPropertySetInfo > aProps = aContent.getProperties();
1085             if ( aProps.is() )
1086             {
1087                 Property aProp = aProps->getPropertyByName( aPropName );
1088                 canRename = !( aProp.Attributes & PropertyAttribute::READONLY );
1089             }
1090             else
1091             {
1092                 canRename = false;
1093             }
1094         }
1095         catch ( Exception const & )
1096         {
1097             canRename = false;
1098         }
1099 
1100         if ( canRename )
1101         {
1102             Any aValue;
1103             aValue <<= OUString( rNewText );
1104             aContent.setPropertyValue( aPropName, aValue );
1105             mpParent->EntryRenamed( aURL, rNewText );
1106 
1107             pData->maURL = aURL;
1108             pEntry->SetUserData( pData );
1109 
1110             bRet = sal_True;
1111         }
1112     }
1113     catch( Exception const & )
1114     {
1115     }
1116 
1117     return bRet;
1118 }
1119 
1120 // -----------------------------------------------------------------------
1121 void ViewTabListBox_Impl::DoQuickSearch( const xub_Unicode& rChar )
1122 {
1123     ::osl::MutexGuard aGuard( maMutex );
1124 
1125     maResetQuickSearch.Stop();
1126 
1127     OUString    aLastText = maQuickSearchText;
1128     sal_uInt32  aLastPos = mnSearchIndex;
1129     sal_Bool    bFound = sal_False;
1130 
1131     maQuickSearchText += OUString( String( rChar ) ).toAsciiLowerCase();
1132 
1133     bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_False );
1134 
1135     if ( !bFound && ( aLastText.getLength() == 1 ) &&
1136          ( aLastText == OUString( String( rChar ) ) ) )
1137     {
1138         mnSearchIndex = aLastPos + 1;
1139         maQuickSearchText = aLastText;
1140         bFound = mpParent->SearchNextEntry( mnSearchIndex, maQuickSearchText, sal_True );
1141     }
1142 
1143     if ( bFound )
1144     {
1145         SvLBoxEntry* pEntry = GetEntry( mnSearchIndex );
1146         if ( pEntry )
1147         {
1148             SelectAll( sal_False );
1149             Select( pEntry );
1150             SetCurEntry( pEntry );
1151             MakeVisible( pEntry );
1152         }
1153         else
1154             bFound = sal_False;
1155     }
1156 
1157     if ( !bFound )
1158         Sound::Beep();
1159 
1160     maResetQuickSearch.Start();
1161 }
1162 
1163 // -----------------------------------------------------------------------
1164 sal_Bool ViewTabListBox_Impl::DoubleClickHdl()
1165 {
1166     SvHeaderTabListBox::DoubleClickHdl();
1167     return sal_False;
1168         // this means "do no additional handling". Especially this means that the SvImpLBox does not
1169         // recognize that the entry at the double click position change after the handler call (which is
1170         // the case if in the handler, our content was replaced)
1171         // If it _would_ recognize this change, it would take this as a reason to select the entry, again
1172         // - which is not what in the case of content replace
1173         // (I really doubt that this behaviour of the SvImpLBox does make any sense at all, but
1174         // who knows ...)
1175         // 07.12.2001 - 95727 - fs@openoffice.org
1176 }
1177 
1178 ::rtl::OUString ViewTabListBox_Impl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eType, sal_Int32 _nPos ) const
1179 {
1180     ::rtl::OUString sRet = SvHeaderTabListBox::GetAccessibleObjectDescription( _eType, _nPos );
1181     if ( ::svt::BBTYPE_TABLECELL == _eType )
1182     {
1183         sal_Int32 nRow = -1;
1184         const sal_uInt16 nColumnCount = GetColumnCount();
1185         if (nColumnCount > 0)
1186             nRow = _nPos / nColumnCount;
1187         SvLBoxEntry* pEntry = GetEntry( nRow );
1188         if ( pEntry )
1189         {
1190             SvtContentEntry* pData = (SvtContentEntry*)pEntry->GetUserData();
1191             if ( pData )
1192             {
1193                 static const String sVar1( RTL_CONSTASCII_USTRINGPARAM( "%1" ) );
1194                 static const String sVar2( RTL_CONSTASCII_USTRINGPARAM( "%2" ) );
1195                 String aText( msAccessibleDescText );
1196                 aText.SearchAndReplace( sVar1, pData->mbIsFolder ? msFolder : msFile );
1197                 aText.SearchAndReplace( sVar2, pData->maURL );
1198                 sRet += ::rtl::OUString( aText );
1199             }
1200         }
1201     }
1202 
1203     return sRet;
1204 }
1205 
1206 // -----------------------------------------------------------------------
1207 sal_Bool ViewTabListBox_Impl::Kill( const OUString& rContent )
1208 {
1209     sal_Bool bRet = sal_True;
1210 
1211     try
1212     {
1213         ::ucbhelper::Content aCnt( rContent, mxCmdEnv );
1214         aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
1215     }
1216     catch( ::com::sun::star::ucb::CommandAbortedException const & )
1217     {
1218         DBG_WARNING( "CommandAbortedException" );
1219         bRet = sal_False;
1220     }
1221     catch( Exception const & )
1222     {
1223         DBG_WARNING( "Any other exception" );
1224         bRet = sal_False;
1225     }
1226 
1227     return bRet;
1228 }
1229 
1230 
1231 
1232 
1233 // -----------------------------------------------------------------------
1234 // class SvtFileView -----------------------------------------------------
1235 // -----------------------------------------------------------------------
1236 
1237 SvtFileView::SvtFileView( Window* pParent, const ResId& rResId,
1238                           sal_Bool bOnlyFolder, sal_Bool bMultiSelection ) :
1239 
1240     Control( pParent, rResId )
1241 {
1242     sal_Int8 nFlags = FILEVIEW_SHOW_ALL;
1243     if ( bOnlyFolder )
1244         nFlags |= FILEVIEW_ONLYFOLDER;
1245     if ( bMultiSelection )
1246         nFlags |= FILEVIEW_MULTISELECTION;
1247 
1248     Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
1249         ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
1250     Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
1251 
1252     mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags, bOnlyFolder );
1253     mpImp->mpView->ForbidEmptyText();
1254 
1255     long pTabs[] = { 5, 20, 180, 320, 400, 600 };
1256     mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
1257     mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size"
1258 
1259     if ( bMultiSelection )
1260         mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION );
1261 
1262     HeaderBar* pHeaderBar = mpImp->mpView->GetHeaderBar();
1263     pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) );
1264     pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) );
1265 }
1266 
1267 SvtFileView::SvtFileView( Window* pParent, const ResId& rResId, sal_Int8 nFlags ) :
1268 
1269     Control( pParent, rResId )
1270 {
1271     Reference< XInteractionHandler > xInteractionHandler = Reference< XInteractionHandler > (
1272         ::comphelper::getProcessServiceFactory()->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uui.InteractionHandler") ) ), UNO_QUERY );
1273     Reference < XCommandEnvironment > xCmdEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler, Reference< XProgressHandler >() );
1274     mpImp = new SvtFileView_Impl( this, xCmdEnv, nFlags,
1275                                   ( nFlags & FILEVIEW_ONLYFOLDER ) == FILEVIEW_ONLYFOLDER );
1276 
1277     if ( ( nFlags & FILEVIEW_SHOW_ALL ) == FILEVIEW_SHOW_ALL )
1278     {
1279         long pTabs[] = { 5, 20, 180, 320, 400, 600 };
1280         mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
1281         mpImp->mpView->SetTabJustify( 2, AdjustRight ); // column "Size"
1282     }
1283     else
1284     {
1285         // show only title
1286         long pTabs[] = { 2, 20, 600 };
1287         mpImp->mpView->SetTabs( &pTabs[0], MAP_PIXEL );
1288     }
1289 
1290     if ( ( nFlags & FILEVIEW_MULTISELECTION ) == FILEVIEW_MULTISELECTION )
1291         mpImp->mpView->SetSelectionMode( MULTIPLE_SELECTION );
1292 
1293     HeaderBar *pHeaderBar = mpImp->mpView->GetHeaderBar();
1294     pHeaderBar->SetSelectHdl( LINK( this, SvtFileView, HeaderSelect_Impl ) );
1295     pHeaderBar->SetEndDragHdl( LINK( this, SvtFileView, HeaderEndDrag_Impl ) );
1296 }
1297 
1298 // -----------------------------------------------------------------------
1299 
1300 SvtFileView::~SvtFileView()
1301 {
1302     // use temp pointer to prevent access of deleted member (GetFocus())
1303     SvtFileView_Impl* pTemp = mpImp;
1304     mpImp = NULL;
1305     delete pTemp;
1306 }
1307 
1308 // -----------------------------------------------------------------------
1309 
1310 void SvtFileView::OpenFolder( const Sequence< OUString >& aContents )
1311 {
1312     mpImp->mpView->ClearAll();
1313     const OUString* pFileProperties  = aContents.getConstArray();
1314     sal_uInt32 i, nCount = aContents.getLength();
1315     for ( i = 0; i < nCount; ++i )
1316     {
1317         String aRow( pFileProperties[i] );
1318         // extract columns
1319         // the columns are: title, type, size, date, target url, is folder, image url
1320         String aTitle, aType, aSize, aDate, aURL, aImageURL;
1321         xub_StrLen nIdx = 0;
1322         aTitle = aRow.GetToken( 0, '\t', nIdx );
1323         aType = aRow.GetToken( 0, '\t', nIdx );
1324         aSize = aRow.GetToken( 0, '\t', nIdx );
1325         aDate = aRow.GetToken( 0, '\t', nIdx );
1326         aURL = aRow.GetToken( 0, '\t', nIdx );
1327         sal_Unicode cFolder = aRow.GetToken( 0, '\t', nIdx ).GetChar(0);
1328         sal_Bool bIsFolder = ( '1' == cFolder );
1329         if ( nIdx != STRING_NOTFOUND )
1330             aImageURL = aRow.GetToken( 0, '\t', nIdx );
1331 
1332         if ( mpImp->mbOnlyFolder && !bIsFolder )
1333             continue;
1334 
1335         // build new row
1336         String aNewRow = aTitle;
1337         aNewRow += '\t';
1338         aNewRow += aType;
1339         aNewRow += '\t';
1340         aNewRow += aSize;
1341         aNewRow += '\t';
1342         aNewRow += aDate;
1343         // detect image
1344         sal_Bool bDoInsert = sal_True;
1345         INetURLObject aObj( aImageURL.Len() > 0 ? aImageURL : aURL );
1346         Image aImage = SvFileInformationManager::GetImage( aObj, sal_False, isHighContrast( this ) );
1347 
1348         if ( bDoInsert )
1349         {
1350             // insert entry and set user data
1351             SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( aNewRow, aImage, aImage, NULL );
1352             SvtContentEntry* pUserData = new SvtContentEntry( aURL, bIsFolder );
1353             pEntry->SetUserData( pUserData );
1354         }
1355     }
1356 
1357     mpImp->InitSelection();
1358     mpImp->ResetCursor();
1359 }
1360 
1361 // -----------------------------------------------------------------------
1362 
1363 String SvtFileView::GetURL( SvLBoxEntry* pEntry ) const
1364 {
1365     String aURL;
1366     if ( pEntry && pEntry->GetUserData() )
1367         aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
1368     return aURL;
1369 }
1370 
1371 // -----------------------------------------------------------------------
1372 
1373 String SvtFileView::GetCurrentURL() const
1374 {
1375     String aURL;
1376     SvLBoxEntry* pEntry = mpImp->mpView->FirstSelected();
1377     if ( pEntry && pEntry->GetUserData() )
1378         aURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
1379     return aURL;
1380 }
1381 // -----------------------------------------------------------------------------
1382 
1383 sal_Bool SvtFileView::CreateNewFolder( const String& rNewFolder )
1384 {
1385     sal_Bool bRet = sal_False;
1386     INetURLObject aObj( mpImp->maViewURL );
1387     aObj.insertName( rNewFolder, false, INetURLObject::LAST_SEGMENT, true, INetURLObject::ENCODE_ALL );
1388     String sURL = aObj.GetMainURL( INetURLObject::NO_DECODE );
1389     if ( ::utl::UCBContentHelper::MakeFolder( sURL, sal_True ) )
1390     {
1391         String sTitle = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
1392         String sEntry = mpImp->FolderInserted( sURL, sTitle );
1393         SvLBoxEntry* pEntry = mpImp->mpView->InsertEntry( sEntry, mpImp->maFolderImage, mpImp->maFolderImage );
1394         SvtContentEntry* pUserData = new SvtContentEntry( sURL, sal_True );
1395         pEntry->SetUserData( pUserData );
1396         mpImp->mpView->MakeVisible( pEntry );
1397         bRet = sal_True;
1398     }
1399     return bRet;
1400 }
1401 
1402 // -----------------------------------------------------------------------
1403 
1404 FileViewResult SvtFileView::PreviousLevel( const FileViewAsyncAction* pAsyncDescriptor )
1405 {
1406     FileViewResult eResult = eFailure;
1407 
1408     String sParentURL;
1409     if ( GetParentURL( sParentURL ) )
1410         eResult = Initialize( sParentURL, mpImp->maCurrentFilter, pAsyncDescriptor, mpBlackList );
1411 
1412     return eResult;
1413 }
1414 
1415 // -----------------------------------------------------------------------
1416 
1417 sal_Bool SvtFileView::GetParentURL( String& rParentURL ) const
1418 {
1419     sal_Bool bRet = sal_False;
1420     try
1421     {
1422         ::ucbhelper::Content aCnt( mpImp->maViewURL, mpImp->mxCmdEnv );
1423         Reference< XContent > xContent( aCnt.get() );
1424         Reference< com::sun::star::container::XChild > xChild( xContent, UNO_QUERY );
1425         if ( xChild.is() )
1426         {
1427             Reference< XContent > xParent( xChild->getParent(), UNO_QUERY );
1428             if ( xParent.is() )
1429             {
1430                 rParentURL = String( xParent->getIdentifier()->getContentIdentifier() );
1431                 bRet = ( rParentURL.Len() > 0 && rParentURL != mpImp->maViewURL );
1432             }
1433         }
1434     }
1435     catch( Exception const & )
1436     {
1437         // perhaps an unkown url protocol (e.g. "private:newdoc")
1438     }
1439 
1440     return bRet;
1441 }
1442 
1443 // -----------------------------------------------------------------------
1444 
1445 const rtl::OString& SvtFileView::GetHelpId( ) const
1446 {
1447     return mpImp->mpView->GetHelpId( );
1448 }
1449 
1450 // -----------------------------------------------------------------------
1451 
1452 void SvtFileView::SetHelpId( const rtl::OString& rHelpId )
1453 {
1454 	mpImp->mpView->SetHelpId( rHelpId );
1455 }
1456 
1457 // -----------------------------------------------------------------------
1458 
1459 void SvtFileView::SetSizePixel( const Size& rNewSize )
1460 {
1461     Control::SetSizePixel( rNewSize );
1462     mpImp->mpView->SetSizePixel( rNewSize );
1463 }
1464 
1465 // -----------------------------------------------------------------------
1466 
1467 void SvtFileView::SetPosSizePixel( const Point& rNewPos, const Size& rNewSize )
1468 {
1469     SetPosPixel( rNewPos );
1470     SetSizePixel( rNewSize );
1471 }
1472 
1473 // -----------------------------------------------------------------------------
1474 sal_Bool SvtFileView::Initialize( const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XContent>& _xContent, const String& rFilter  )
1475 {
1476     WaitObject aWaitCursor( this );
1477 
1478     mpImp->Clear();
1479     ::ucbhelper::Content aContent(_xContent, mpImp->mxCmdEnv );
1480     FileViewResult eResult = mpImp->GetFolderContent_Impl( FolderDescriptor( aContent ), NULL );
1481     OSL_ENSURE( eResult != eStillRunning, "SvtFileView::Initialize: this was expected to be synchronous!" );
1482     if ( eResult != eSuccess )
1483         return sal_False;
1484 
1485     mpImp->FilterFolderContent_Impl( rFilter );
1486 
1487     mpImp->SortFolderContent_Impl(); // possibly not necessary!!!!!!!!!!
1488     mpImp->CreateDisplayText_Impl();
1489     mpImp->OpenFolder_Impl();
1490 
1491     mpImp->maOpenDoneLink.Call( this );
1492     return sal_True;
1493 }
1494 
1495 // -----------------------------------------------------------------------
1496 FileViewResult SvtFileView::Initialize(
1497     const String& rURL,
1498     const String& rFilter,
1499     const FileViewAsyncAction* pAsyncDescriptor,
1500     const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList  )
1501 {
1502     WaitObject aWaitCursor( this );
1503     mpBlackList = rBlackList;
1504 
1505     String sPushURL( mpImp->maViewURL );
1506 
1507     mpImp->maViewURL = rURL;
1508     FileViewResult eResult = ExecuteFilter( rFilter, pAsyncDescriptor );
1509     switch ( eResult )
1510     {
1511     case eFailure:
1512     case eTimeout:
1513         mpImp->maViewURL = sPushURL;
1514         return eResult;
1515 
1516     case eStillRunning:
1517         OSL_ENSURE( pAsyncDescriptor, "SvtFileView::Initialize: we told it to read synchronously!" );
1518     case eSuccess:
1519         return eResult;
1520     }
1521 
1522     OSL_ENSURE( sal_False, "SvtFileView::Initialize: unreachable!" );
1523     return eFailure;
1524 }
1525 
1526 // -----------------------------------------------------------------------
1527 FileViewResult SvtFileView::Initialize(
1528     const String& rURL,
1529     const String& rFilter,
1530     const FileViewAsyncAction* pAsyncDescriptor )
1531 {
1532     return Initialize( rURL, rFilter, pAsyncDescriptor, ::com::sun::star::uno::Sequence< ::rtl::OUString >());
1533 }
1534 
1535 // -----------------------------------------------------------------------
1536 
1537 // -----------------------------------------------------------------------
1538 sal_Bool SvtFileView::Initialize( const Sequence< OUString >& aContents )
1539 {
1540     WaitObject aWaitCursor( this );
1541 
1542     mpImp->maViewURL = String();
1543     mpImp->maCurrentFilter = mpImp->maAllFilter;
1544 
1545     mpImp->Clear();
1546     mpImp->CreateVector_Impl( aContents );
1547     mpImp->SortFolderContent_Impl();
1548 
1549     mpImp->OpenFolder_Impl();
1550 
1551     mpImp->maOpenDoneLink.Call( this );
1552 
1553     return sal_True;
1554 }
1555 
1556 // -----------------------------------------------------------------------
1557 
1558 FileViewResult SvtFileView::ExecuteFilter( const String& rFilter, const FileViewAsyncAction* pAsyncDescriptor )
1559 {
1560     mpImp->maCurrentFilter = rFilter;
1561     mpImp->maCurrentFilter.ToLowerAscii();
1562 
1563     mpImp->Clear();
1564     FileViewResult eResult = mpImp->GetFolderContent_Impl( mpImp->maViewURL, pAsyncDescriptor, mpBlackList );
1565     OSL_ENSURE( ( eResult != eStillRunning ) || pAsyncDescriptor, "SvtFileView::ExecuteFilter: we told it to read synchronously!" );
1566     return eResult;
1567 }
1568 
1569 // -----------------------------------------------------------------------
1570 
1571 void SvtFileView::CancelRunningAsyncAction()
1572 {
1573     mpImp->CancelRunningAsyncAction();
1574 }
1575 
1576 // -----------------------------------------------------------------------
1577 
1578 void SvtFileView::SetNoSelection()
1579 {
1580     mpImp->mpView->SelectAll( sal_False );
1581 }
1582 
1583 // -----------------------------------------------------------------------
1584 
1585 void SvtFileView::GetFocus()
1586 {
1587     Control::GetFocus();
1588     if ( mpImp && mpImp->mpView )
1589         mpImp->mpView->GrabFocus();
1590 }
1591 
1592 // -----------------------------------------------------------------------
1593 
1594 void SvtFileView::ResetCursor()
1595 {
1596     mpImp->ResetCursor();
1597 }
1598 
1599 // -----------------------------------------------------------------------
1600 
1601 void SvtFileView::SetSelectHdl( const Link& rHdl )
1602 {
1603     mpImp->SetSelectHandler( rHdl );
1604 }
1605 
1606 // -----------------------------------------------------------------------
1607 
1608 void SvtFileView::SetDoubleClickHdl( const Link& rHdl )
1609 {
1610     mpImp->mpView->SetDoubleClickHdl( rHdl );
1611 }
1612 
1613 // -----------------------------------------------------------------------
1614 
1615 sal_uLong SvtFileView::GetSelectionCount() const
1616 {
1617     return mpImp->mpView->GetSelectionCount();
1618 }
1619 
1620 // -----------------------------------------------------------------------
1621 
1622 SvLBoxEntry* SvtFileView::FirstSelected() const
1623 {
1624     return mpImp->mpView->FirstSelected();
1625 }
1626 
1627 // -----------------------------------------------------------------------
1628 
1629 SvLBoxEntry* SvtFileView::NextSelected( SvLBoxEntry* pEntry ) const
1630 {
1631     return mpImp->mpView->NextSelected( pEntry );
1632 }
1633 
1634 // -----------------------------------------------------------------------
1635 
1636 void SvtFileView::EnableAutoResize()
1637 {
1638     mpImp->mpView->EnableAutoResize();
1639 }
1640 
1641 // -----------------------------------------------------------------------
1642 
1643 void SvtFileView::SetFocus()
1644 {
1645     mpImp->mpView->GrabFocus();
1646 }
1647 
1648 // -----------------------------------------------------------------------
1649 const String& SvtFileView::GetViewURL() const
1650 {
1651     return mpImp->maViewURL;
1652 }
1653 
1654 // -----------------------------------------------------------------------
1655 void SvtFileView::SetOpenDoneHdl( const Link& rHdl )
1656 {
1657     mpImp->maOpenDoneLink = rHdl;
1658 }
1659 
1660 // -----------------------------------------------------------------------
1661 void SvtFileView::EnableContextMenu( sal_Bool bEnable )
1662 {
1663     mpImp->EnableContextMenu( bEnable );
1664 }
1665 
1666 // -----------------------------------------------------------------------
1667 void SvtFileView::EnableDelete( sal_Bool bEnable )
1668 {
1669     mpImp->EnableDelete( bEnable );
1670 }
1671 
1672 void SvtFileView::EnableNameReplacing( sal_Bool bEnable )
1673 {
1674     mpImp->EnableNameReplacing( bEnable );
1675 }
1676 
1677 // -----------------------------------------------------------------------
1678 void SvtFileView::EndInplaceEditing( bool _bCancel )
1679 {
1680     return mpImp->EndEditing( _bCancel );
1681 }
1682 
1683 // -----------------------------------------------------------------------
1684 IMPL_LINK( SvtFileView, HeaderSelect_Impl, HeaderBar*, pBar )
1685 {
1686     DBG_ASSERT( pBar, "no headerbar" );
1687     sal_uInt16 nItemID = pBar->GetCurItemId();
1688 
1689     HeaderBarItemBits nBits;
1690 
1691     // clear the arrow of the recently used column
1692     if ( nItemID != mpImp->mnSortColumn )
1693     {
1694         if ( !nItemID )
1695         {
1696             // first call -> remove arrow from title column,
1697             // because another column is the sort column
1698             nItemID = mpImp->mnSortColumn;
1699             mpImp->mnSortColumn = COLUMN_TITLE;
1700         }
1701         nBits = pBar->GetItemBits( mpImp->mnSortColumn );
1702         nBits &= ~( HIB_UPARROW | HIB_DOWNARROW );
1703         pBar->SetItemBits( mpImp->mnSortColumn, nBits );
1704     }
1705 
1706     nBits = pBar->GetItemBits( nItemID );
1707 
1708     sal_Bool bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
1709 
1710     if ( bUp )
1711     {
1712         nBits &= ~HIB_UPARROW;
1713         nBits |= HIB_DOWNARROW;
1714     }
1715     else
1716     {
1717         nBits &= ~HIB_DOWNARROW;
1718         nBits |= HIB_UPARROW;
1719     }
1720 
1721     pBar->SetItemBits( nItemID, nBits );
1722     mpImp->Resort_Impl( nItemID, !bUp );
1723     return 1;
1724 }
1725 
1726 // -----------------------------------------------------------------------
1727 IMPL_LINK( SvtFileView, HeaderEndDrag_Impl, HeaderBar*, pBar )
1728 {
1729     if ( !pBar->IsItemMode() )
1730     {
1731         Size aSize;
1732         sal_uInt16 nTabs = pBar->GetItemCount();
1733         long nTmpSize = 0;
1734 
1735         for ( sal_uInt16 i = 1; i <= nTabs; ++i )
1736         {
1737             long nWidth = pBar->GetItemSize(i);
1738             aSize.Width() =  nWidth + nTmpSize;
1739             nTmpSize += nWidth;
1740             mpImp->mpView->SetTab( i, aSize.Width(), MAP_PIXEL );
1741         }
1742     }
1743 
1744     return 0;
1745 }
1746 
1747 // -----------------------------------------------------------------------
1748 String SvtFileView::GetConfigString() const
1749 {
1750     String sRet;
1751     HeaderBar* pBar = mpImp->mpView->GetHeaderBar();
1752     DBG_ASSERT( pBar, "invalid headerbar" );
1753 
1754     // sort order
1755     sRet += String::CreateFromInt32( mpImp->mnSortColumn );
1756     sRet += ';';
1757     HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn );
1758     sal_Bool bUp = ( ( nBits & HIB_UPARROW ) == HIB_UPARROW );
1759     sRet += bUp ? '1' : '0';
1760     sRet += ';';
1761 
1762     sal_uInt16 nCount = pBar->GetItemCount();
1763     for ( sal_uInt16 i = 0; i < nCount; ++i )
1764     {
1765         sal_uInt16 nId = pBar->GetItemId(i);
1766         sRet += String::CreateFromInt32( nId );
1767         sRet += ';';
1768         sRet += String::CreateFromInt32( pBar->GetItemSize( nId ) );
1769         sRet += ';';
1770     }
1771 
1772     sRet.EraseTrailingChars( ';' );
1773     return sRet;
1774 }
1775 
1776 // -----------------------------------------------------------------------
1777 void SvtFileView::SetConfigString( const String& rCfgStr )
1778 {
1779     HeaderBar* pBar = mpImp->mpView->GetHeaderBar();
1780     DBG_ASSERT( pBar, "invalid headerbar" );
1781 
1782     sal_uInt16 nIdx = 0;
1783     mpImp->mnSortColumn = (sal_uInt16)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
1784     sal_Bool bUp = (sal_Bool)(sal_uInt16)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
1785     HeaderBarItemBits nBits = pBar->GetItemBits( mpImp->mnSortColumn );
1786 
1787     if ( bUp )
1788     {
1789         nBits &= ~HIB_UPARROW;
1790         nBits |= HIB_DOWNARROW;
1791     }
1792     else
1793     {
1794         nBits &= ~HIB_DOWNARROW;
1795         nBits |= HIB_UPARROW;
1796     }
1797     pBar->SetItemBits( mpImp->mnSortColumn, nBits );
1798 
1799     while ( nIdx != STRING_NOTFOUND )
1800     {
1801         sal_uInt16 nItemId = (sal_uInt16)rCfgStr.GetToken( 0, ';', nIdx ).ToInt32();
1802         pBar->SetItemSize( nItemId, rCfgStr.GetToken( 0, ';', nIdx ).ToInt32() );
1803     }
1804 
1805     HeaderSelect_Impl( pBar );
1806     HeaderEndDrag_Impl( pBar );
1807 }
1808 
1809 // -----------------------------------------------------------------------
1810 void SvtFileView::SetUrlFilter( const IUrlFilter* _pFilter )
1811 {
1812     mpImp->mpUrlFilter = _pFilter;
1813 }
1814 
1815 // -----------------------------------------------------------------------
1816 const IUrlFilter* SvtFileView::GetUrlFilter( ) const
1817 {
1818     return mpImp->mpUrlFilter;
1819 }
1820 
1821 // -----------------------------------------------------------------------
1822 void SvtFileView::StateChanged( StateChangedType nStateChange )
1823 {
1824     if ( nStateChange == STATE_CHANGE_ENABLE )
1825         Invalidate();
1826     Control::StateChanged( nStateChange );
1827 }
1828 
1829 // -----------------------------------------------------------------------
1830 // class NameTranslator_Impl
1831 // -----------------------------------------------------------------------
1832 
1833 NameTranslator_Impl::NameTranslator_Impl( void ) :
1834     mpActFolder( NULL )
1835 {
1836 }
1837 
1838 NameTranslator_Impl::NameTranslator_Impl( const INetURLObject& rActualFolder )
1839 {
1840     mpActFolder = new NameTranslationList( rActualFolder );
1841 }
1842 
1843 NameTranslator_Impl::~NameTranslator_Impl()
1844 {
1845     if( mpActFolder )
1846         delete mpActFolder;
1847 }
1848 
1849 void NameTranslator_Impl::UpdateTranslationTable()
1850 {
1851     if( mpActFolder )
1852         mpActFolder->Update();
1853 }
1854 
1855 void NameTranslator_Impl::SetActualFolder( const INetURLObject& rActualFolder )
1856 {
1857     HashedEntry aActFolder( rActualFolder );
1858 
1859     if( mpActFolder )
1860     {
1861         if( *mpActFolder != aActFolder )
1862         {
1863             delete mpActFolder;
1864             mpActFolder = new NameTranslationList( rActualFolder );
1865         }
1866     }
1867     else
1868         mpActFolder = new NameTranslationList( rActualFolder );
1869 }
1870 
1871 sal_Bool NameTranslator_Impl::GetTranslation( const OUString& rOrg, OUString& rTrans ) const
1872 {
1873     sal_Bool bRet = sal_False;
1874 
1875     if( mpActFolder )
1876     {
1877         const OUString* pTrans = mpActFolder->Translate( rOrg );
1878         if( pTrans )
1879         {
1880             rTrans = *pTrans;
1881             bRet = sal_True;
1882         }
1883     }
1884 
1885     return bRet;
1886 }
1887 
1888 const String* NameTranslator_Impl::GetTransTableFileName() const
1889 {
1890     return mpActFolder? &mpActFolder->GetTransTableFileName() : NULL;
1891 }
1892 
1893 // -----------------------------------------------------------------------
1894 // class SvtFileView_Impl
1895 // -----------------------------------------------------------------------
1896 
1897 SvtFileView_Impl::SvtFileView_Impl( SvtFileView* pAntiImpl, Reference < XCommandEnvironment > xEnv, sal_Int16 nFlags, sal_Bool bOnlyFolder )
1898 
1899     :mpAntiImpl                 ( pAntiImpl )
1900     ,m_eAsyncActionResult       ( ::svt::ERROR )
1901     ,m_bRunningAsyncAction      ( false )
1902     ,m_bAsyncActionCancelled    ( false )
1903     ,mpNameTrans                ( NULL )
1904     ,mpUrlFilter                ( NULL )
1905     ,mnSortColumn               ( COLUMN_TITLE )
1906     ,mbAscending                ( sal_True )
1907     ,mbOnlyFolder               ( bOnlyFolder )
1908     ,mbReplaceNames             ( sal_False )
1909     ,mnSuspendSelectCallback    ( 0 )
1910     ,mbIsFirstResort            ( sal_True )
1911     ,aIntlWrapper               ( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() )
1912     ,maFolderImage              ( SvtResId( IMG_SVT_FOLDER ) )
1913     ,mxCmdEnv ( xEnv )
1914 
1915 {
1916     maAllFilter = String::CreateFromAscii( "*.*" );
1917     mpView = new ViewTabListBox_Impl( mpAntiImpl, this, nFlags );
1918     mpView->EnableCellFocus();
1919 }
1920 
1921 // -----------------------------------------------------------------------
1922 SvtFileView_Impl::~SvtFileView_Impl()
1923 {
1924     Clear();
1925 
1926     // use temp pointer to prevent access of deleted member (GetFocus())
1927     ViewTabListBox_Impl* pTemp = mpView;
1928     mpView = NULL;
1929     delete pTemp;
1930 }
1931 
1932 // -----------------------------------------------------------------------
1933 void SvtFileView_Impl::Clear()
1934 {
1935     ::osl::MutexGuard aGuard( maMutex );
1936 
1937     std::vector< SortingData_Impl* >::iterator aIt;
1938 
1939     for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
1940         delete (*aIt);
1941 
1942     maContent.clear();
1943 
1944     if( mpNameTrans )
1945         DELETEZ( mpNameTrans );
1946 }
1947 
1948 // -----------------------------------------------------------------------
1949 FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
1950     const String& rFolder,
1951     const FileViewAsyncAction* pAsyncDescriptor,
1952     const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
1953 {
1954     ::osl::ClearableMutexGuard aGuard( maMutex );
1955     INetURLObject aFolderObj( rFolder );
1956     DBG_ASSERT( aFolderObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
1957 
1958     // prepare name translation
1959     SetActualFolder( aFolderObj );
1960 
1961     FolderDescriptor aFolder( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ) );
1962 
1963     aGuard.clear();
1964     return GetFolderContent_Impl( aFolder, pAsyncDescriptor, rBlackList );
1965 }
1966 
1967 // -----------------------------------------------------------------------
1968 FileViewResult SvtFileView_Impl::GetFolderContent_Impl(
1969     const FolderDescriptor& _rFolder,
1970     const FileViewAsyncAction* pAsyncDescriptor,
1971     const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rBlackList )
1972 {
1973     DBG_TESTSOLARMUTEX();
1974     ::osl::ClearableMutexGuard aGuard( maMutex );
1975 
1976     OSL_ENSURE( !m_pContentEnumerator.is(), "SvtFileView_Impl::GetFolderContent_Impl: still running another enumeration!" );
1977     m_pContentEnumerator = new ::svt::FileViewContentEnumerator(
1978         mpView->GetCommandEnvironment(), maContent, maMutex, mbReplaceNames ? mpNameTrans : NULL );
1979         // TODO: should we cache and re-use this thread?
1980 
1981     if ( !pAsyncDescriptor )
1982     {
1983         ::svt::EnumerationResult eResult = m_pContentEnumerator->enumerateFolderContentSync( _rFolder, mpUrlFilter, rBlackList );
1984         if ( ::svt::SUCCESS == eResult )
1985         {
1986             implEnumerationSuccess();
1987             m_pContentEnumerator = NULL;
1988             return eSuccess;
1989         }
1990         m_pContentEnumerator = NULL;
1991         return eFailure;
1992     }
1993 
1994     m_bRunningAsyncAction = true;
1995     m_bAsyncActionCancelled = false;
1996     m_eAsyncActionResult = ::svt::ERROR;
1997     m_aAsyncActionFinished.reset();
1998 
1999     // don't (yet) set m_aCurrentAsyncActionHandler to pTimeout->aFinishHandler.
2000     // By definition, this handler *only* get's called when the result cannot be obtained
2001     // during the minimum wait time, so it is only set below, when needed.
2002     m_aCurrentAsyncActionHandler = Link();
2003 
2004     // minimum time to wait
2005     ::std::auto_ptr< TimeValue > pTimeout( new TimeValue );
2006     sal_Int32 nMinTimeout = pAsyncDescriptor->nMinTimeout;
2007     OSL_ENSURE( nMinTimeout > 0, "SvtFileView_Impl::GetFolderContent_Impl: invalid minimum timeout!" );
2008     if ( nMinTimeout <= 0 )
2009         nMinTimeout = sal_Int32( 1000L );
2010     pTimeout->Seconds = nMinTimeout / 1000L;
2011     pTimeout->Nanosec = ( nMinTimeout % 1000L ) * 1000000L;
2012 
2013     m_pContentEnumerator->enumerateFolderContent( _rFolder, mpUrlFilter, this );
2014 
2015     // wait until the enumeration is finished
2016     // for this, release our own mutex (which is used by the enumerator thread)
2017     aGuard.clear();
2018 
2019     ::osl::Condition::Result eResult = ::osl::Condition::result_ok;
2020     {
2021         // also release the SolarMutex. Not all code which is needed during the enumeration
2022         // is Solar-Thread-Safe, in particular there is some code which needs to access
2023         // string resources (and our resource system relies on the SolarMutex :()
2024         ReleaseSolarMutex aSolarRelease;
2025 
2026         // now wait. Note that if we didn't get an pAsyncDescriptor, then this is an infinite wait.
2027         eResult = m_aAsyncActionFinished.wait( pTimeout.get() );
2028     }
2029 
2030     ::osl::MutexGuard aGuard2( maMutex );
2031     if ( ::osl::Condition::result_timeout == eResult )
2032     {
2033         // maximum time to wait
2034         OSL_ENSURE( !m_pCancelAsyncTimer.get(), "SvtFileView_Impl::GetFolderContent_Impl: there's still a previous timer!" );
2035         m_pCancelAsyncTimer = new CallbackTimer( this );
2036         sal_Int32 nMaxTimeout = pAsyncDescriptor->nMaxTimeout;
2037         OSL_ENSURE( nMaxTimeout > nMinTimeout,
2038             "SvtFileView_Impl::GetFolderContent_Impl: invalid maximum timeout!" );
2039         if ( nMaxTimeout <= nMinTimeout )
2040             nMaxTimeout = nMinTimeout + 5000;
2041         m_pCancelAsyncTimer->setRemainingTime( TTimeValue( nMaxTimeout - nMinTimeout ) );
2042             // we already waited for nMinTimeout milliseconds, so take this into account
2043         m_pCancelAsyncTimer->start();
2044 
2045         m_aCurrentAsyncActionHandler = pAsyncDescriptor->aFinishHandler;
2046         DBG_ASSERT( m_aCurrentAsyncActionHandler.IsSet(), "SvtFileView_Impl::GetFolderContent_Impl: nobody interested when it's finished?" );
2047         mpView->ClearAll();
2048         return eStillRunning;
2049     }
2050 
2051     m_bRunningAsyncAction = false;
2052     switch ( m_eAsyncActionResult )
2053     {
2054     case ::svt::SUCCESS:
2055         return eSuccess;
2056 
2057     case ::svt::ERROR:
2058         return eFailure;
2059 
2060     case ::svt::RUNNING:
2061         return eStillRunning;
2062     }
2063 
2064     DBG_ERRORFILE( "SvtFileView_Impl::GetFolderContent_Impl: unreachable!" );
2065     return eFailure;
2066 }
2067 
2068 // -----------------------------------------------------------------------
2069 void SvtFileView_Impl::FilterFolderContent_Impl( const OUString &rFilter )
2070 {
2071     sal_Bool bHideTransFile = mbReplaceNames && mpNameTrans;
2072 
2073     String sHideEntry;
2074     if( bHideTransFile )
2075     {
2076         const String* pTransTableFileName = mpNameTrans->GetTransTableFileName();
2077         if( pTransTableFileName )
2078         {
2079             sHideEntry = *pTransTableFileName;
2080             sHideEntry.ToUpperAscii();
2081         }
2082         else
2083             bHideTransFile = sal_False;
2084     }
2085 
2086     if ( !bHideTransFile &&
2087         ( !rFilter.getLength() || ( rFilter.compareToAscii( ALL_FILES_FILTER ) == COMPARE_EQUAL ) ) )
2088         // when replacing names, there is always something to filter (no view of ".nametranslation.table")
2089         return;
2090 
2091     ::osl::MutexGuard aGuard( maMutex );
2092 
2093     if ( maContent.empty() )
2094         return;
2095 
2096     // count (estimate) the number of filter tokens
2097     sal_Int32 nTokens=0;
2098     const sal_Unicode* pStart = rFilter.getStr();
2099     const sal_Unicode* pEnd = pStart + rFilter.getLength();
2100     while ( pStart != pEnd )
2101         if ( *pStart++ == ';' )
2102             ++nTokens;
2103 
2104     // collect the filter tokens
2105     ::std::vector< WildCard > aFilters;
2106     FilterMatch::createWildCardFilterList(rFilter,aFilters);
2107 
2108 
2109     // do the filtering
2110     ::std::vector< SortingData_Impl* >::iterator aContentLoop = maContent.begin();
2111     String sCompareString;
2112     do
2113     {
2114         if ( (*aContentLoop)->mbIsFolder )
2115             ++aContentLoop;
2116         else
2117         {
2118             // normalize the content title (we always match case-insensitive)
2119             // 91872 - 11.09.2001 - frank.schoenheit@sun.com
2120             sCompareString = (*aContentLoop)->GetFileName(); // filter works on file name, not on title!
2121             sal_Bool bDelete;
2122 
2123             if( bHideTransFile && sCompareString == sHideEntry )
2124                 bDelete = sal_True;
2125             else
2126             {
2127                 // search for the first filter which matches
2128                 ::std::vector< WildCard >::const_iterator pMatchingFilter =
2129                     ::std::find_if(
2130                         aFilters.begin(),
2131                         aFilters.end(),
2132                         FilterMatch( sCompareString )
2133                     );
2134 
2135                 bDelete = aFilters.end() == pMatchingFilter;
2136             }
2137 
2138             if( bDelete )
2139             {
2140                 // none of the filters did match
2141                 delete (*aContentLoop);
2142 
2143                 if ( maContent.begin() == aContentLoop )
2144                 {
2145                     maContent.erase( aContentLoop );
2146                     aContentLoop = maContent.begin();
2147                 }
2148                 else
2149                 {
2150                     std::vector< SortingData_Impl* >::iterator aDelete = aContentLoop;
2151                     --aContentLoop; // move the iterator to a position which is not invalidated by the erase
2152                     maContent.erase( aDelete );
2153                     ++aContentLoop; // this is now the next one ....
2154                 }
2155             }
2156             else
2157                 ++aContentLoop;
2158         }
2159     }
2160     while ( aContentLoop != maContent.end() );
2161 }
2162 
2163 // -----------------------------------------------------------------------
2164 IMPL_LINK( SvtFileView_Impl, SelectionMultiplexer, void*, _pSource )
2165 {
2166     return mnSuspendSelectCallback ? 0L : m_aSelectHandler.Call( _pSource );
2167 }
2168 
2169 // -----------------------------------------------------------------------
2170 void SvtFileView_Impl::SetSelectHandler( const Link& _rHdl )
2171 {
2172     m_aSelectHandler = _rHdl;
2173 
2174     Link aMasterHandler;
2175     if ( m_aSelectHandler.IsSet() )
2176         aMasterHandler = LINK( this, SvtFileView_Impl, SelectionMultiplexer );
2177 
2178     mpView->SetSelectHdl( aMasterHandler );
2179 }
2180 
2181 // -----------------------------------------------------------------------
2182 void SvtFileView_Impl::InitSelection()
2183 {
2184     mpView->SelectAll( sal_False );
2185     SvLBoxEntry* pFirst = mpView->First();
2186     if ( pFirst )
2187         mpView->SetCursor( pFirst, sal_True );
2188 }
2189 
2190 // -----------------------------------------------------------------------
2191 void SvtFileView_Impl::OpenFolder_Impl()
2192 {
2193     ::osl::MutexGuard aGuard( maMutex );
2194 
2195     mpView->SetUpdateMode( sal_False );
2196     mpView->ClearAll();
2197 
2198     std::vector< SortingData_Impl* >::iterator aIt;
2199 
2200     for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2201     {
2202         if ( mbOnlyFolder && ! (*aIt)->mbIsFolder )
2203             continue;
2204 
2205         // insert entry and set user data
2206         SvLBoxEntry* pEntry = mpView->InsertEntry( (*aIt)->maDisplayText,
2207                                                    (*aIt)->maImage,
2208                                                    (*aIt)->maImage );
2209 
2210         SvtContentEntry* pUserData = new SvtContentEntry( (*aIt)->maTargetURL,
2211                                                           (*aIt)->mbIsFolder );
2212         pEntry->SetUserData( pUserData );
2213     }
2214 
2215     InitSelection();
2216 
2217     ++mnSuspendSelectCallback;
2218     mpView->SetUpdateMode( sal_True );
2219     --mnSuspendSelectCallback;
2220 
2221     ResetCursor();
2222 }
2223 
2224 // -----------------------------------------------------------------------
2225 void SvtFileView_Impl::ResetCursor()
2226 {
2227     // deselect
2228     SvLBoxEntry* pEntry = mpView->FirstSelected();
2229     if ( pEntry )
2230         mpView->Select( pEntry, sal_False );
2231     // set cursor to the first entry
2232     mpView->SetCursor( mpView->First(), sal_True );
2233     mpView->Update();
2234 }
2235 
2236 // -----------------------------------------------------------------------
2237 void SvtFileView_Impl::CancelRunningAsyncAction()
2238 {
2239     DBG_TESTSOLARMUTEX();
2240     ::osl::MutexGuard aGuard( maMutex );
2241     if ( !m_pContentEnumerator.is() )
2242         return;
2243 
2244     m_bAsyncActionCancelled = true;
2245     m_pContentEnumerator->cancel();
2246     m_bRunningAsyncAction = false;
2247 
2248     m_pContentEnumerator = NULL;
2249     if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() )
2250         m_pCancelAsyncTimer->stop();
2251     m_pCancelAsyncTimer = NULL;
2252 }
2253 
2254 //-----------------------------------------------------------------------
2255 void SvtFileView_Impl::onTimeout( CallbackTimer* )
2256 {
2257     ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
2258     ::osl::MutexGuard aGuard( maMutex );
2259     if ( !m_bRunningAsyncAction )
2260         // there might have been a race condition while we waited for the mutex
2261         return;
2262 
2263     CancelRunningAsyncAction();
2264 
2265     if ( m_aCurrentAsyncActionHandler.IsSet() )
2266     {
2267         Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( eTimeout ) );
2268         m_aCurrentAsyncActionHandler = Link();
2269     }
2270 }
2271 
2272 //-----------------------------------------------------------------------
2273 void SvtFileView_Impl::enumerationDone( ::svt::EnumerationResult _eResult )
2274 {
2275     ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
2276     ::osl::MutexGuard aGuard( maMutex );
2277 
2278     m_pContentEnumerator = NULL;
2279     if ( m_pCancelAsyncTimer.is() && m_pCancelAsyncTimer->isTicking() )
2280         m_pCancelAsyncTimer->stop();
2281     m_pCancelAsyncTimer = NULL;
2282 
2283     if ( m_bAsyncActionCancelled )
2284         // this is to prevent race conditions
2285         return;
2286 
2287     m_eAsyncActionResult = _eResult;
2288     m_bRunningAsyncAction = false;
2289 
2290     m_aAsyncActionFinished.set();
2291 
2292     if ( svt::SUCCESS == _eResult )
2293         implEnumerationSuccess();
2294 
2295     if ( m_aCurrentAsyncActionHandler.IsSet() )
2296     {
2297         Application::PostUserEvent( m_aCurrentAsyncActionHandler, reinterpret_cast< void* >( m_eAsyncActionResult ) );
2298         m_aCurrentAsyncActionHandler = Link();
2299     }
2300 }
2301 
2302 //-----------------------------------------------------------------------
2303 void SvtFileView_Impl::implEnumerationSuccess()
2304 {
2305     FilterFolderContent_Impl( maCurrentFilter );
2306     SortFolderContent_Impl();
2307     CreateDisplayText_Impl();
2308     OpenFolder_Impl();
2309     maOpenDoneLink.Call( mpAntiImpl );
2310 }
2311 
2312 // -----------------------------------------------------------------------
2313 void SvtFileView_Impl::ReplaceTabWithString( OUString& aValue )
2314 {
2315     OUString aTab     = OUString::createFromAscii( "\t" );
2316     OUString aTabString = OUString::createFromAscii( "%09" );
2317     sal_Int32 iPos;
2318 
2319     while ( ( iPos = aValue.indexOf( aTab ) ) >= 0 )
2320        aValue = aValue.replaceAt( iPos, 1, aTabString );
2321 }
2322 
2323 // -----------------------------------------------------------------------
2324 void SvtFileView_Impl::CreateDisplayText_Impl()
2325 {
2326     ::osl::MutexGuard aGuard( maMutex );
2327 
2328     OUString aValue;
2329     OUString aTab     = OUString::createFromAscii( "\t" );
2330     OUString aDateSep = OUString::createFromAscii( ", " );
2331 
2332     std::vector< SortingData_Impl* >::iterator aIt;
2333 
2334     for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2335     {
2336         // title, type, size, date
2337         aValue = (*aIt)->GetTitle();
2338         // #83004# --------------------
2339         ReplaceTabWithString( aValue );
2340         aValue += aTab;
2341         aValue += (*aIt)->maType;
2342         aValue += aTab;
2343         // folders don't have a size
2344         if ( ! (*aIt)->mbIsFolder )
2345             aValue += CreateExactSizeText_Impl( (*aIt)->maSize );
2346         aValue += aTab;
2347         // set the date, but volumes have no date
2348         if ( ! (*aIt)->mbIsFolder || ! (*aIt)->mbIsVolume )
2349         {
2350             SvtSysLocale aSysLocale;
2351             const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
2352             aValue += rLocaleData.getDate( (*aIt)->maModDate );
2353             aValue += aDateSep;
2354             aValue += rLocaleData.getTime( (*aIt)->maModDate );
2355         }
2356         (*aIt)->maDisplayText = aValue;
2357 
2358         // detect image
2359         if ( (*aIt)->mbIsFolder )
2360         {
2361             ::svtools::VolumeInfo aVolInfo( (*aIt)->mbIsVolume, (*aIt)->mbIsRemote,
2362                                             (*aIt)->mbIsRemoveable, (*aIt)->mbIsFloppy,
2363                                             (*aIt)->mbIsCompactDisc );
2364             (*aIt)->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, sal_False, isHighContrast( mpView ) );
2365         }
2366         else
2367             (*aIt)->maImage = SvFileInformationManager::GetFileImage( INetURLObject( (*aIt)->maTargetURL ), sal_False, isHighContrast( mpView ));
2368     }
2369 }
2370 
2371 // -----------------------------------------------------------------------
2372 // this function converts the sequence of strings into a vector of SortingData
2373 // the string should have the form :
2374 // title \t type \t size \t date \t target url \t is folder \t image url
2375 
2376 void SvtFileView_Impl::CreateVector_Impl( const Sequence < OUString > &rList )
2377 {
2378     ::osl::MutexGuard aGuard( maMutex );
2379 
2380     OUString aTab     = OUString::createFromAscii( "\t" );
2381 
2382     sal_uInt32 nCount = (sal_uInt32) rList.getLength();
2383 
2384     for( sal_uInt32 i = 0; i < nCount; i++ )
2385     {
2386         SortingData_Impl*   pEntry = new SortingData_Impl;
2387         OUString            aValue = rList[i];
2388         OUString            aDisplayText;
2389         sal_Int32           nIndex = 0;
2390 
2391         // get the title
2392         pEntry->SetNewTitle( aValue.getToken( 0, '\t', nIndex ) );
2393         aDisplayText = pEntry->GetTitle();
2394         // #83004# --------------------
2395         ReplaceTabWithString( aDisplayText );
2396         aDisplayText += aTab;
2397 
2398         // get the type
2399         if ( nIndex >= 0 )
2400         {
2401             pEntry->maType = aValue.getToken( 0, '\t', nIndex );
2402             aDisplayText += pEntry->maType;
2403         }
2404         aDisplayText += aTab;
2405 
2406         // get the size
2407         if ( nIndex >= 0 )
2408         {
2409             OUString aSize = aValue.getToken( 0, '\t', nIndex );
2410             aDisplayText += aSize;
2411 
2412             if ( aSize.getLength() )
2413                 pEntry->maSize = aSize.toInt64();
2414         }
2415         aDisplayText += aTab;
2416 
2417         // get the date
2418         if ( nIndex >= 0 )
2419         {
2420             OUString aDate = aValue.getToken( 0, '\t', nIndex );
2421             aDisplayText += aDate;
2422 
2423             if ( aDate.getLength() )
2424             {
2425                 DBG_ERRORFILE( "Don't know, how to convert date" );
2426                 ;// convert date string to date
2427             }
2428         }
2429         // get the target url
2430         if ( nIndex >= 0 )
2431         {
2432             pEntry->maTargetURL = aValue.getToken( 0, '\t', nIndex );
2433         }
2434         // get the size
2435         if ( nIndex >= 0 )
2436         {
2437             OUString aBool = aValue.getToken( 0, '\t', nIndex );
2438             if ( aBool.getLength() )
2439                 pEntry->mbIsFolder = aBool.toBoolean();
2440         }
2441         // get the image url
2442         if ( nIndex >= 0 )
2443         {
2444             pEntry->maImageURL = aValue.getToken( 0, '\t', nIndex );
2445         }
2446 
2447         // set the display text
2448         pEntry->maDisplayText = aDisplayText;
2449 
2450         // detect the image
2451         INetURLObject aObj( pEntry->maImageURL.getLength() ? pEntry->maImageURL : pEntry->maTargetURL );
2452         pEntry->maImage = SvFileInformationManager::GetImage( aObj, sal_False, isHighContrast( mpView ) );
2453 
2454         maContent.push_back( pEntry );
2455     }
2456 }
2457 
2458 // -----------------------------------------------------------------------
2459 void SvtFileView_Impl::Resort_Impl( sal_Int16 nColumn, sal_Bool bAscending )
2460 {
2461     ::osl::MutexGuard aGuard( maMutex );
2462 
2463     if ( ( nColumn == mnSortColumn ) &&
2464          ( bAscending == mbAscending ) )
2465          return;
2466 
2467     // reset the quick search index
2468     mpView->ResetQuickSearch_Impl( NULL );
2469 
2470     String aEntryURL;
2471     SvLBoxEntry* pEntry = mpView->GetCurEntry();
2472     if ( pEntry && pEntry->GetUserData() )
2473         aEntryURL = ( (SvtContentEntry*)pEntry->GetUserData() )->maURL;
2474 
2475     mnSortColumn = nColumn;
2476     mbAscending = bAscending;
2477 
2478     SortFolderContent_Impl();
2479     OpenFolder_Impl();
2480 
2481     if ( !mbIsFirstResort )
2482     {
2483         sal_uLong nPos = GetEntryPos( aEntryURL );
2484         if ( nPos < mpView->GetEntryCount() )
2485         {
2486             pEntry = mpView->GetEntry( nPos );
2487 
2488             ++mnSuspendSelectCallback;  // #i15668# - 2004-04-25 - fs@openoffice.org
2489             mpView->SetCurEntry( pEntry );
2490             --mnSuspendSelectCallback;
2491         }
2492     }
2493     else
2494         mbIsFirstResort = sal_False;
2495 }
2496 
2497 // -----------------------------------------------------------------------
2498 static sal_Bool                 gbAscending = sal_True;
2499 static sal_Int16                gnColumn = COLUMN_TITLE;
2500 static const CollatorWrapper*   pCollatorWrapper = NULL;
2501 
2502 /* this functions returns true, if aOne is less then aTwo
2503 */
2504 sal_Bool CompareSortingData_Impl( SortingData_Impl* const aOne, SortingData_Impl* const aTwo )
2505 {
2506     DBG_ASSERT( pCollatorWrapper, "*CompareSortingData_Impl(): Can't work this way!" );
2507 
2508     sal_Int32   nComp;
2509     sal_Bool    bRet = sal_False;
2510     sal_Bool    bEqual = sal_False;
2511 
2512     if ( aOne->mbIsFolder != aTwo->mbIsFolder )
2513     {
2514         if ( aOne->mbIsFolder )
2515             bRet = sal_True;
2516         else
2517             bRet = sal_False;
2518 
2519         // !!! pb: #100376# folder always on top
2520         if ( !gbAscending )
2521             bRet = !bRet;
2522     }
2523     else
2524     {
2525         switch ( gnColumn )
2526         {
2527             case COLUMN_TITLE:
2528                 // compare case insensitiv first
2529                 nComp = pCollatorWrapper->compareString( aOne->GetLowerTitle(), aTwo->GetLowerTitle() );
2530 
2531                 if ( nComp == 0 )
2532                     nComp = pCollatorWrapper->compareString( aOne->GetTitle(), aTwo->GetTitle() );
2533 
2534                 if ( nComp < 0 )
2535                     bRet = sal_True;
2536                 else if ( nComp > 0 )
2537                     bRet = sal_False;
2538                 else
2539                     bEqual = sal_True;
2540                 break;
2541             case COLUMN_TYPE:
2542                 nComp = pCollatorWrapper->compareString( aOne->maType, aTwo->maType );
2543                 if ( nComp < 0 )
2544                     bRet = sal_True;
2545                 else if ( nComp > 0 )
2546                     bRet = sal_False;
2547                 else
2548                     bEqual = sal_True;
2549                 break;
2550             case COLUMN_SIZE:
2551                 if ( aOne->maSize < aTwo->maSize )
2552                     bRet = sal_True;
2553                 else if ( aOne->maSize > aTwo->maSize )
2554                     bRet = sal_False;
2555                 else
2556                     bEqual = sal_True;
2557                 break;
2558             case COLUMN_DATE:
2559                 if ( aOne->maModDate < aTwo->maModDate )
2560                     bRet = sal_True;
2561                 else if ( aOne->maModDate > aTwo->maModDate )
2562                     bRet = sal_False;
2563                 else
2564                     bEqual = sal_True;
2565                 break;
2566             default:
2567                 DBG_WARNING( "CompareSortingData_Impl: Compare unknown type!" );
2568                 bRet = sal_False;
2569         }
2570     }
2571 
2572     // when the two elements are equal, we must not return sal_True (which would
2573     // happen if we just return ! ( a < b ) when not sorting ascending )
2574     if ( bEqual )
2575         return sal_False;
2576 
2577     return gbAscending ? bRet : !bRet;
2578 }
2579 
2580 // -----------------------------------------------------------------------
2581 void SvtFileView_Impl::SortFolderContent_Impl()
2582 {
2583     ::osl::MutexGuard aGuard( maMutex );
2584 
2585     sal_uInt32 nSize = maContent.size();
2586 
2587     if ( nSize > 1 )
2588     {
2589         gbAscending = mbAscending;
2590         gnColumn = mnSortColumn;
2591         pCollatorWrapper = aIntlWrapper.getCaseCollator();
2592 
2593         std::stable_sort( maContent.begin(), maContent.end(), CompareSortingData_Impl );
2594 
2595         pCollatorWrapper = NULL;
2596     }
2597 }
2598 
2599 // -----------------------------------------------------------------------
2600 void SvtFileView_Impl::EntryRemoved( const OUString& rURL )
2601 {
2602     ::osl::MutexGuard aGuard( maMutex );
2603 
2604     std::vector< SortingData_Impl* >::iterator aIt;
2605 
2606     for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2607     {
2608         if ( (*aIt)->maTargetURL == rURL )
2609         {
2610             maContent.erase( aIt );
2611             break;
2612         }
2613     }
2614 }
2615 
2616 // -----------------------------------------------------------------------
2617 void SvtFileView_Impl::EntryRenamed( OUString& rURL,
2618                                      const OUString& rTitle )
2619 {
2620     ::osl::MutexGuard aGuard( maMutex );
2621 
2622     std::vector< SortingData_Impl* >::iterator aIt;
2623 
2624     for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2625     {
2626         if ( (*aIt)->maTargetURL == rURL )
2627         {
2628             (*aIt)->SetNewTitle( rTitle );
2629             OUString aDisplayText = (*aIt)->maDisplayText;
2630             sal_Int32 nIndex = aDisplayText.indexOf( '\t' );
2631 
2632             if ( nIndex > 0 )
2633                 (*aIt)->maDisplayText = aDisplayText.replaceAt( 0, nIndex, rTitle );
2634 
2635             INetURLObject aURLObj( rURL );
2636             aURLObj.SetName( rTitle, INetURLObject::ENCODE_ALL );
2637 
2638             rURL = aURLObj.GetMainURL( INetURLObject::NO_DECODE );
2639 
2640             (*aIt)->maTargetURL = rURL;
2641             break;
2642         }
2643     }
2644 }
2645 
2646 // -----------------------------------------------------------------------
2647 String SvtFileView_Impl::FolderInserted( const OUString& rURL, const OUString& rTitle )
2648 {
2649     ::osl::MutexGuard aGuard( maMutex );
2650 
2651     SortingData_Impl* pData = new SortingData_Impl;
2652 
2653     pData->SetNewTitle( rTitle );
2654     pData->maSize     = 0;
2655     pData->mbIsFolder = sal_True;
2656     pData->maTargetURL   = rURL;
2657 
2658     INetURLObject aURLObj( rURL );
2659 
2660     ::svtools::VolumeInfo aVolInfo;
2661     pData->maType = SvFileInformationManager::GetFolderDescription( aVolInfo );
2662     pData->maImage = SvFileInformationManager::GetFolderImage( aVolInfo, sal_False, isHighContrast( mpView ) );
2663 
2664     OUString aValue;
2665     OUString aTab     = OUString::createFromAscii( "\t" );
2666     OUString aDateSep = OUString::createFromAscii( ", " );
2667 
2668     // title, type, size, date
2669     aValue = pData->GetTitle();
2670     // #83004# --------------------
2671     ReplaceTabWithString( aValue );
2672     aValue += aTab;
2673     aValue += pData->maType;
2674     aValue += aTab;
2675     // folders don't have a size
2676     aValue += aTab;
2677     // set the date
2678     SvtSysLocale aSysLocale;
2679     const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
2680     aValue += rLocaleData.getDate( pData->maModDate );
2681     aValue += aDateSep;
2682     aValue += rLocaleData.getTime( pData->maModDate );
2683 
2684     pData->maDisplayText = aValue;
2685     maContent.push_back( pData );
2686 
2687     return String( aValue );
2688 }
2689 
2690 // -----------------------------------------------------------------------
2691 sal_uLong SvtFileView_Impl::GetEntryPos( const OUString& rURL )
2692 {
2693     ::osl::MutexGuard aGuard( maMutex );
2694 
2695     std::vector< SortingData_Impl* >::iterator aIt;
2696     sal_uLong   nPos = 0;
2697 
2698     for ( aIt = maContent.begin(); aIt != maContent.end(); aIt++ )
2699     {
2700         if ( (*aIt)->maTargetURL == rURL )
2701             return nPos;
2702         nPos += 1;
2703     }
2704 
2705     return nPos;
2706 }
2707 
2708 // -----------------------------------------------------------------------
2709 sal_Bool SvtFileView_Impl::SearchNextEntry( sal_uInt32& nIndex, const OUString& rTitle, sal_Bool bWrapAround )
2710 {
2711     ::osl::MutexGuard aGuard( maMutex );
2712 
2713     sal_uInt32 nEnd = maContent.size();
2714     sal_uInt32 nStart = nIndex;
2715     while ( nIndex < nEnd )
2716     {
2717         SortingData_Impl* pData = maContent[ nIndex ];
2718         if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 )
2719             return sal_True;
2720         nIndex += 1;
2721     }
2722 
2723     if ( bWrapAround )
2724     {
2725         nIndex = 0;
2726         while ( nIndex < nEnd && nIndex <= nStart )
2727         {
2728             SortingData_Impl* pData = maContent[ nIndex ];
2729             if ( rTitle.compareTo( pData->GetLowerTitle(), rTitle.getLength() ) == 0 )
2730                 return sal_True;
2731             nIndex += 1;
2732         }
2733     }
2734 
2735     return sal_False;
2736 }
2737 
2738 // -----------------------------------------------------------------------
2739 void SvtFileView_Impl::SetActualFolder( const INetURLObject& rActualFolder )
2740 {
2741     if( mbReplaceNames )
2742     {
2743         if( mpNameTrans )
2744             mpNameTrans->SetActualFolder( rActualFolder );
2745         else
2746             mpNameTrans = new NameTranslator_Impl( rActualFolder );
2747     }
2748 }
2749 
2750 namespace svtools {
2751 
2752 // -----------------------------------------------------------------------
2753 // QueryDeleteDlg_Impl
2754 // -----------------------------------------------------------------------
2755 
2756 QueryDeleteDlg_Impl::QueryDeleteDlg_Impl
2757 (
2758     Window* pParent,
2759     const String& rName      // Eintragsname
2760 ) :
2761 
2762     ModalDialog( pParent, SvtResId( DLG_SVT_QUERYDELETE ) ),
2763 
2764     _aEntryLabel  ( this, SvtResId( TXT_ENTRY ) ),
2765     _aEntry       ( this, SvtResId( TXT_ENTRYNAME ) ),
2766     _aQueryMsg    ( this, SvtResId( TXT_QUERYMSG ) ),
2767     _aYesButton   ( this, SvtResId( BTN_YES ) ),
2768     _aAllButton   ( this, SvtResId( BTN_ALL ) ),
2769     _aNoButton    ( this, SvtResId( BTN_NO ) ),
2770     _aCancelButton( this, SvtResId( BTN_CANCEL ) )
2771 
2772 {
2773     FreeResource();
2774 
2775     // Handler
2776     Link aLink( STATIC_LINK( this, QueryDeleteDlg_Impl, ClickLink ) );
2777     _aYesButton.SetClickHdl( aLink );
2778     _aAllButton.SetClickHdl( aLink );
2779     _aNoButton.SetClickHdl( aLink );
2780 
2781     // Anzeige der spezifizierten Texte
2782 
2783     WinBits nTmpStyle = _aEntry.GetStyle();
2784     nTmpStyle |= WB_PATHELLIPSIS;
2785     _aEntry.SetStyle( nTmpStyle );
2786     _aEntry.SetText( rName );
2787 }
2788 
2789 // -----------------------------------------------------------------------
2790 
2791 IMPL_STATIC_LINK( QueryDeleteDlg_Impl, ClickLink, PushButton*, pBtn )
2792 {
2793     if ( pBtn == &pThis->_aYesButton )
2794         pThis->_eResult = QUERYDELETE_YES;
2795     else if ( pBtn == &pThis->_aNoButton )
2796         pThis->_eResult = QUERYDELETE_NO;
2797     else if ( pBtn == &pThis->_aAllButton )
2798         pThis->_eResult = QUERYDELETE_ALL;
2799     else if ( pBtn == &pThis->_aCancelButton )
2800         pThis->_eResult = QUERYDELETE_CANCEL;
2801 
2802     pThis->EndDialog( RET_OK );
2803 
2804     return 0;
2805 }
2806 
2807 }
2808 
2809