LCOV - code coverage report
Current view: top level - svtools/source/control - inettbc.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 603 0.2 %
Date: 2015-06-13 12:38:46 Functions: 2 41 4.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #ifdef UNX
      21             : #include <pwd.h>
      22             : #include <sys/types.h>
      23             : #endif
      24             : 
      25             : #include <svtools/inettbc.hxx>
      26             : #include <com/sun/star/uno/Any.hxx>
      27             : #include <com/sun/star/uno/Reference.hxx>
      28             : #include <com/sun/star/beans/Property.hpp>
      29             : #include <com/sun/star/beans/PropertyValue.hpp>
      30             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      31             : #include <com/sun/star/sdbc/XResultSet.hpp>
      32             : #include <com/sun/star/sdbc/XRow.hpp>
      33             : #include <com/sun/star/task/XInteractionHandler.hpp>
      34             : #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
      35             : #include <com/sun/star/ucb/UniversalContentBroker.hpp>
      36             : #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
      37             : #include <com/sun/star/ucb/XCommandProcessor2.hpp>
      38             : #include <com/sun/star/ucb/XProgressHandler.hpp>
      39             : #include <com/sun/star/ucb/XContentAccess.hpp>
      40             : #include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
      41             : #include <comphelper/processfactory.hxx>
      42             : #include <comphelper/string.hxx>
      43             : #include <rtl/instance.hxx>
      44             : #include <salhelper/thread.hxx>
      45             : #include <osl/mutex.hxx>
      46             : #include <vcl/builderfactory.hxx>
      47             : #include <vcl/svapp.hxx>
      48             : #include <vcl/toolbox.hxx>
      49             : #include <unotools/historyoptions.hxx>
      50             : #include <svl/eitem.hxx>
      51             : #include <svl/stritem.hxx>
      52             : #include <svl/itemset.hxx>
      53             : #include <svl/urihelper.hxx>
      54             : #include <unotools/pathoptions.hxx>
      55             : #include <ucbhelper/commandenvironment.hxx>
      56             : #include <ucbhelper/content.hxx>
      57             : #include <unotools/localfilehelper.hxx>
      58             : #include <unotools/ucbhelper.hxx>
      59             : #include <svtools/asynclink.hxx>
      60             : #include <svl/urlfilter.hxx>
      61             : 
      62             : #include <vector>
      63             : #include <algorithm>
      64             : 
      65             : using namespace ::ucbhelper;
      66             : using namespace ::utl;
      67             : using namespace ::com::sun::star;
      68             : using namespace ::com::sun::star::beans;
      69             : using namespace ::com::sun::star::lang;
      70             : using namespace ::com::sun::star::sdbc;
      71             : using namespace ::com::sun::star::task;
      72             : using namespace ::com::sun::star::ucb;
      73             : using namespace ::com::sun::star::uno;
      74             : 
      75           0 : class SvtURLBox_Impl
      76             : {
      77             : public:
      78             :     std::vector<OUString>      aURLs;
      79             :     std::vector<OUString>      aCompletions;
      80             :     std::vector<WildCard>      m_aFilters;
      81             : 
      82             :     static bool TildeParsing( OUString& aText, OUString& aBaseUrl );
      83             : 
      84           0 :     inline SvtURLBox_Impl( )
      85           0 :     {
      86           0 :         FilterMatch::createWildCardFilterList(OUString(),m_aFilters);
      87           0 :     }
      88             : };
      89             : 
      90             : class SvtMatchContext_Impl: public salhelper::Thread
      91             : {
      92             :     static ::osl::Mutex*            pDirMutex;
      93             : 
      94             :     std::vector<OUString>           aPickList;
      95             :     std::vector<OUString>           aCompletions;
      96             :     std::vector<OUString>           aURLs;
      97             :     svtools::AsynchronLink          aLink;
      98             :     OUString                        aBaseURL;
      99             :     OUString                        aText;
     100             :     VclPtr<SvtURLBox>               pBox;
     101             :     bool                            bOnlyDirectories;
     102             :     bool                            bNoSelection;
     103             : 
     104             :     osl::Mutex mutex_;
     105             :     bool stopped_;
     106             :     css::uno::Reference< css::ucb::XCommandProcessor > processor_;
     107             :     sal_Int32 commandId_;
     108             : 
     109             :     DECL_LINK(                      Select_Impl, void* );
     110             : 
     111             :     virtual                         ~SvtMatchContext_Impl();
     112             :     virtual void                    execute() SAL_OVERRIDE;
     113             :     void                            doExecute();
     114             :     void                            Insert( const OUString& rCompletion, const OUString& rURL, bool bForce = false);
     115             :     void                            ReadFolder( const OUString& rURL, const OUString& rMatch, bool bSmart );
     116             :     static void                     FillPicklist(std::vector<OUString>& rPickList);
     117             : 
     118             : public:
     119             :                                     SvtMatchContext_Impl( SvtURLBox* pBoxP, const OUString& rText );
     120             :     void                            Stop();
     121             : };
     122             : 
     123             : namespace
     124             : {
     125             :     struct theSvtMatchContextMutex
     126             :         : public rtl::Static< ::osl::Mutex, theSvtMatchContextMutex > {};
     127             : }
     128             : 
     129           0 : SvtMatchContext_Impl::SvtMatchContext_Impl(
     130             :     SvtURLBox* pBoxP, const OUString& rText )
     131             :     : Thread( "SvtMatchContext_Impl" )
     132             :     , aLink( LINK( this, SvtMatchContext_Impl, Select_Impl ) )
     133             :     , aBaseURL( pBoxP->aBaseURL )
     134             :     , aText( rText )
     135             :     , pBox( pBoxP )
     136             :     , bOnlyDirectories( pBoxP->bOnlyDirectories )
     137             :     , bNoSelection( pBoxP->bNoSelection )
     138             :     , stopped_(false)
     139           0 :     , commandId_(0)
     140             : {
     141           0 :     aLink.CreateMutex();
     142             : 
     143           0 :     FillPicklist( aPickList );
     144           0 : }
     145             : 
     146           0 : SvtMatchContext_Impl::~SvtMatchContext_Impl()
     147             : {
     148           0 :     aLink.ClearPendingCall();
     149           0 : }
     150             : 
     151           0 : void SvtMatchContext_Impl::FillPicklist(std::vector<OUString>& rPickList)
     152             : {
     153             :     // Einlesung der Historypickliste
     154           0 :     Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( ePICKLIST );
     155           0 :     sal_uInt32 nCount = seqPicklist.getLength();
     156             : 
     157           0 :     for( sal_uInt32 nItem=0; nItem < nCount; nItem++ )
     158             :     {
     159           0 :         Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
     160             : 
     161           0 :         OUString sTitle;
     162           0 :         INetURLObject aURL;
     163             : 
     164           0 :         sal_uInt32 nPropertyCount = seqPropertySet.getLength();
     165             : 
     166           0 :         for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ )
     167             :         {
     168           0 :             if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_TITLE )
     169             :             {
     170           0 :                 seqPropertySet[nProperty].Value >>= sTitle;
     171           0 :                 aURL.SetURL( sTitle );
     172           0 :                 rPickList.insert(rPickList.begin() + nItem, aURL.GetMainURL(INetURLObject::DECODE_WITH_CHARSET));
     173           0 :                 break;
     174             :             }
     175             :         }
     176           0 :     }
     177           0 : }
     178             : 
     179           0 : void SvtMatchContext_Impl::Stop()
     180             : {
     181           0 :     css::uno::Reference< css::ucb::XCommandProcessor > proc;
     182           0 :     sal_Int32 id(0);
     183             :     {
     184           0 :         osl::MutexGuard g(mutex_);
     185           0 :         if (!stopped_) {
     186           0 :             stopped_ = true;
     187           0 :             proc = processor_;
     188           0 :             id = commandId_;
     189           0 :         }
     190             :     }
     191           0 :     if (proc.is()) {
     192           0 :         proc->abort(id);
     193             :     }
     194           0 :     terminate();
     195           0 : }
     196             : 
     197           0 : void SvtMatchContext_Impl::execute( )
     198             : {
     199           0 :     doExecute();
     200           0 :     aLink.Call( this );
     201           0 : }
     202             : 
     203             : 
     204             : // This method is called via AsynchronLink, so it has the SolarMutex and
     205             : // calling solar code ( VCL ... ) is safe. It is called when the thread is
     206             : // terminated ( finished work or stopped ). Cancelling the thread via
     207             : // Cancellable does not discard the information gained so far, it
     208             : // inserts all collected completions into the listbox.
     209             : 
     210           0 : IMPL_LINK_NOARG( SvtMatchContext_Impl, Select_Impl )
     211             : {
     212             :     // avoid recursion through cancel button
     213             :     {
     214           0 :         osl::MutexGuard g(mutex_);
     215           0 :         if (stopped_) {
     216             :             // Completion was stopped, no display:
     217           0 :             return 0;
     218           0 :         }
     219             :     }
     220             : 
     221           0 :     pBox->bAutoCompleteMode = true;
     222             : 
     223             :     // did we filter completions which otherwise would have been valid?
     224             :     // (to be filled below)
     225           0 :     bool bValidCompletionsFiltered = false;
     226             : 
     227             :     // insert all completed strings into the listbox
     228           0 :     pBox->Clear();
     229             : 
     230           0 :     for(std::vector<OUString>::iterator i = aCompletions.begin(); i != aCompletions.end(); ++i)
     231             :     {
     232           0 :         OUString sCompletion(*i);
     233             : 
     234             :         // convert the file into an URL
     235           0 :         OUString sURL( sCompletion );
     236           0 :         ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sCompletion, sURL );
     237             :             // note: if this doesn't work, we're not interested in: we're checking the
     238             :             // untouched sCompletion then
     239             : 
     240           0 :         if ( !sURL.isEmpty() && !sURL.endsWith("/") )
     241             :         {
     242           0 :             OUString sUpperURL( sURL.toAsciiUpperCase() );
     243             : 
     244           0 :             if ( ::std::none_of( pBox->pImp->m_aFilters.begin(),
     245           0 :                                  pBox->pImp->m_aFilters.end(),
     246           0 :                                  FilterMatch( sUpperURL ) ) )
     247             :             {   // this URL is not allowed
     248           0 :                 bValidCompletionsFiltered = true;
     249           0 :                 continue;
     250           0 :             }
     251             :         }
     252             : 
     253           0 :         pBox->InsertEntry( sCompletion );
     254           0 :     }
     255             : 
     256           0 :     if( !bNoSelection && !aCompletions.empty() && !bValidCompletionsFiltered )
     257             :     {
     258             :         // select the first one
     259           0 :         OUString aTmp( pBox->GetEntry(0) );
     260           0 :         pBox->SetText( aTmp );
     261           0 :         pBox->SetSelection( Selection( aText.getLength(), aTmp.getLength() ) );
     262             :     }
     263             : 
     264             :     // transfer string lists to listbox and forget them
     265           0 :     pBox->pImp->aURLs = aURLs;
     266           0 :     pBox->pImp->aCompletions = aCompletions;
     267           0 :     aURLs.clear();
     268           0 :     aCompletions.clear();
     269             : 
     270             :     // force listbox to resize ( it may be open )
     271           0 :     pBox->Resize();
     272             : 
     273             :     // the box has this control as a member so we have to set that member
     274             :     // to zero before deleting ourself.
     275           0 :     pBox->pCtx.clear();
     276             : 
     277           0 :     return 0;
     278             : }
     279             : 
     280             : 
     281           0 : void SvtMatchContext_Impl::Insert( const OUString& rCompletion,
     282             :                                    const OUString& rURL,
     283             :                                    bool bForce )
     284             : {
     285           0 :     if( !bForce )
     286             :     {
     287             :         // avoid doubles
     288           0 :         if(find(aCompletions.begin(), aCompletions.end(), OUString(rCompletion)) != aCompletions.end())
     289           0 :             return;
     290             :     }
     291             : 
     292           0 :     aCompletions.push_back(rCompletion);
     293           0 :     aURLs.push_back(rURL);
     294             : }
     295             : 
     296             : 
     297           0 : void SvtMatchContext_Impl::ReadFolder( const OUString& rURL,
     298             :                                        const OUString& rMatch,
     299             :                                        bool bSmart )
     300             : {
     301             :     // check folder to scan
     302           0 :     if( !UCBContentHelper::IsFolder( rURL ) )
     303           0 :         return;
     304             : 
     305           0 :     bool bPureHomePath = false;
     306             : #ifdef UNX
     307           0 :     bPureHomePath = aText.startsWith( "~" ) && aText.indexOf( '/' ) == -1;
     308             : #endif
     309             : 
     310             :     bool bExectMatch = bPureHomePath
     311           0 :                 || aText == "."
     312           0 :                 || aText.endsWith("/.")
     313           0 :                 || aText.endsWith("/..");
     314             : 
     315             :     // for pure home paths ( ~username ) the '.' at the end of rMatch
     316             :     // means that it poits to root catalog
     317             :     // this is done only for file contents since home paths parsing is useful only for them
     318           0 :     if ( bPureHomePath && rMatch == "file:///." )
     319             :     {
     320             :         // a home that refers to /
     321             : 
     322           0 :         OUString aNewText( aText );
     323           0 :         aNewText += "/";
     324           0 :         Insert( aNewText, rURL, true );
     325             : 
     326           0 :         return;
     327             :     }
     328             : 
     329             :     // string to match with
     330           0 :     INetURLObject aMatchObj( rMatch );
     331           0 :     OUString aMatchName;
     332             : 
     333           0 :     if ( rURL != aMatchObj.GetMainURL( INetURLObject::NO_DECODE ) )
     334             :     {
     335           0 :         aMatchName = aMatchObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
     336             : 
     337             :         // matching is always done case insensitive, but completion will be case sensitive and case preserving
     338           0 :         aMatchName = aMatchName.toAsciiLowerCase();
     339             : 
     340             :         // if the matchstring ends with a slash, we must search for this also
     341           0 :         if ( rMatch.endsWith("/") )
     342           0 :             aMatchName += "/";
     343             :     }
     344             : 
     345           0 :     sal_Int32 nMatchLen = aMatchName.getLength();
     346             : 
     347           0 :     INetURLObject aFolderObj( rURL );
     348             :     DBG_ASSERT( aFolderObj.GetProtocol() != INetProtocol::NotValid, "Invalid URL!" );
     349             : 
     350             :     try
     351             :     {
     352             :         Content aCnt( aFolderObj.GetMainURL( INetURLObject::NO_DECODE ),
     353             :                       new ::ucbhelper::CommandEnvironment( uno::Reference< XInteractionHandler >(),
     354           0 :                                                      uno::Reference< XProgressHandler >() ),
     355           0 :                       comphelper::getProcessComponentContext() );
     356           0 :         uno::Reference< XResultSet > xResultSet;
     357           0 :         Sequence< OUString > aProps(2);
     358           0 :         OUString* pProps = aProps.getArray();
     359           0 :         pProps[0] = "Title";
     360           0 :         pProps[1] = "IsFolder";
     361             : 
     362             :         try
     363             :         {
     364           0 :             uno::Reference< XDynamicResultSet > xDynResultSet;
     365           0 :             ResultSetInclude eInclude = INCLUDE_FOLDERS_AND_DOCUMENTS;
     366           0 :             if ( bOnlyDirectories )
     367           0 :                 eInclude = INCLUDE_FOLDERS_ONLY;
     368             : 
     369           0 :             xDynResultSet = aCnt.createDynamicCursor( aProps, eInclude );
     370             : 
     371           0 :             uno::Reference < XAnyCompareFactory > xCompare;
     372             :             uno::Reference < XSortedDynamicResultSetFactory > xSRSFac =
     373           0 :                 SortedDynamicResultSetFactory::create( ::comphelper::getProcessComponentContext() );
     374             : 
     375           0 :             Sequence< NumberedSortingInfo > aSortInfo( 2 );
     376           0 :             NumberedSortingInfo* pInfo = aSortInfo.getArray();
     377           0 :             pInfo[ 0 ].ColumnIndex = 2;
     378           0 :             pInfo[ 0 ].Ascending   = false;
     379           0 :             pInfo[ 1 ].ColumnIndex = 1;
     380           0 :             pInfo[ 1 ].Ascending   = true;
     381             : 
     382           0 :             uno::Reference< XDynamicResultSet > xDynamicResultSet;
     383           0 :             xDynamicResultSet =
     384           0 :                 xSRSFac->createSortedDynamicResultSet( xDynResultSet, aSortInfo, xCompare );
     385             : 
     386           0 :             if ( xDynamicResultSet.is() )
     387             :             {
     388           0 :                 xResultSet = xDynamicResultSet->getStaticResultSet();
     389           0 :             }
     390             :         }
     391           0 :         catch( ::com::sun::star::uno::Exception& ) {}
     392             : 
     393           0 :         if ( xResultSet.is() )
     394             :         {
     395           0 :             uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
     396           0 :             uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
     397             : 
     398             :             try
     399             :             {
     400           0 :                 while ( schedule() && xResultSet->next() )
     401             :                 {
     402           0 :                     OUString   aURL      = xContentAccess->queryContentIdentifierString();
     403           0 :                     OUString   aTitle    = xRow->getString(1);
     404           0 :                     bool   bIsFolder = xRow->getBoolean(2);
     405             : 
     406             :                     // matching is always done case insensitive, but completion will be case sensitive and case preserving
     407           0 :                     aTitle = aTitle.toAsciiLowerCase();
     408             : 
     409           0 :                     if (
     410           0 :                         !nMatchLen ||
     411           0 :                         (bExectMatch && aMatchName == aTitle) ||
     412           0 :                         (!bExectMatch && aMatchName.compareTo(aTitle, nMatchLen) == 0)
     413             :                        )
     414             :                     {
     415             :                         // all names fit if matchstring is empty
     416           0 :                         INetURLObject aObj( aURL );
     417           0 :                         sal_Unicode aDelimiter = '/';
     418           0 :                         if ( bSmart )
     419             :                             // when parsing is done "smart", the delimiter must be "guessed"
     420           0 :                             aObj.getFSysPath( (INetURLObject::FSysStyle)(INetURLObject::FSYS_DETECT & ~INetURLObject::FSYS_VOS), &aDelimiter );
     421             : 
     422           0 :                         if ( bIsFolder )
     423           0 :                             aObj.setFinalSlash();
     424             : 
     425             :                         // get the last name of the URL
     426           0 :                         OUString aMatch = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
     427           0 :                         OUString aInput( aText );
     428           0 :                         if ( nMatchLen )
     429             :                         {
     430           0 :                             if (aText.endsWith(".") || bPureHomePath)
     431             :                             {
     432             :                                 // if a "special folder" URL was typed, don't touch the user input
     433           0 :                                 aMatch = aMatch.copy( nMatchLen );
     434             :                             }
     435             :                             else
     436             :                             {
     437             :                                 // make the user input case preserving
     438             :                                 DBG_ASSERT( aInput.getLength() >= nMatchLen, "Suspicious Matching!" );
     439           0 :                                 aInput = aInput.copy( 0, aInput.getLength() - nMatchLen );
     440             :                             }
     441             :                         }
     442             : 
     443           0 :                         aInput += aMatch;
     444             : 
     445             :                         // folders should get a final slash automatically
     446           0 :                         if ( bIsFolder )
     447           0 :                             aInput += OUString(aDelimiter);
     448             : 
     449           0 :                         Insert( aInput, aObj.GetMainURL( INetURLObject::NO_DECODE ), true );
     450             :                     }
     451           0 :                 }
     452             :             }
     453           0 :             catch( ::com::sun::star::uno::Exception& )
     454             :             {
     455           0 :             }
     456           0 :         }
     457             :     }
     458           0 :     catch( ::com::sun::star::uno::Exception& )
     459             :     {
     460           0 :     }
     461             : }
     462             : 
     463             : 
     464           0 : OUString SvtURLBox::ParseSmart( const OUString& _aText, const OUString& _aBaseURL, const OUString& aWorkDir )
     465             : {
     466           0 :     OUString aMatch;
     467           0 :     OUString aText = _aText;
     468           0 :     OUString aBaseURL = _aBaseURL;
     469             : 
     470             :     // parse ~ for Unix systems
     471             :     // does nothing for Windows
     472           0 :     if( !SvtURLBox_Impl::TildeParsing( aText, aBaseURL ) )
     473           0 :         return OUString();
     474             : 
     475           0 :     if( !aBaseURL.isEmpty() )
     476             :     {
     477           0 :         INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL );
     478             : 
     479             :         // if a base URL is set the string may be parsed relative
     480           0 :         if( aText.startsWith( "/" ) )
     481             :         {
     482             :             // text starting with slashes means absolute file URLs
     483           0 :             OUString aTemp = INetURLObject::GetScheme( eBaseProt );
     484             : 
     485             :             // file URL must be correctly encoded!
     486             :             OUString aTextURL = INetURLObject::encode( aText, INetURLObject::PART_FPATH,
     487           0 :                                                      INetURLObject::ENCODE_ALL );
     488           0 :             aTemp += aTextURL;
     489             : 
     490           0 :             INetURLObject aTmp( aTemp );
     491           0 :             if ( !aTmp.HasError() && aTmp.GetProtocol() != INetProtocol::NotValid )
     492           0 :                 aMatch = aTmp.GetMainURL( INetURLObject::NO_DECODE );
     493             :         }
     494             :         else
     495             :         {
     496           0 :             OUString aSmart( aText );
     497           0 :             INetURLObject aObj( aBaseURL );
     498             : 
     499             :             // HRO: I suppose this hack should only be done for Windows !!!???
     500             : #ifdef WNT
     501             :             // HRO: INetURLObject::smatRel2Abs does not recognize '\\' as a relative path
     502             :             //      but in case of "\\\\" INetURLObject is right - this is an absolute path !
     503             : 
     504             :             if( aText.startsWith("\\") && (aText.getLength() < 2 || aText[ 1 ] != '\\') )
     505             :             {
     506             :                 // cut to first segment
     507             :                 OUString aTmp = INetURLObject::GetScheme( eBaseProt );
     508             :                 aTmp += "/";
     509             :                 aTmp += aObj.getName( 0, true, INetURLObject::DECODE_WITH_CHARSET );
     510             :                 aObj.SetURL( aTmp );
     511             : 
     512             :                 aSmart = aSmart.copy(1);
     513             :             }
     514             : #endif
     515             :             // base URL must be a directory !
     516           0 :             aObj.setFinalSlash();
     517             : 
     518             :             // take base URL and append current input
     519           0 :             bool bWasAbsolute = false;
     520             : #ifdef UNX
     521           0 :             INetURLObject::FSysStyle eStyle = static_cast< INetURLObject::FSysStyle >( INetURLObject::FSYS_VOS | INetURLObject::FSYS_UNX | INetURLObject::FSYS_DOS );
     522             :             // encode file URL correctly
     523           0 :             aSmart = INetURLObject::encode( aSmart, INetURLObject::PART_FPATH, INetURLObject::ENCODE_ALL );
     524             :             INetURLObject aTmp( aObj.smartRel2Abs(
     525           0 :                 aSmart, bWasAbsolute, false, INetURLObject::WAS_ENCODED, RTL_TEXTENCODING_UTF8, false, eStyle ) );
     526             : #else
     527             :             INetURLObject aTmp( aObj.smartRel2Abs( aSmart, bWasAbsolute ) );
     528             : #endif
     529             : 
     530           0 :             if ( aText.endsWith(".") )
     531             :                 // INetURLObject appends a final slash for the directories "." and "..", this is a bug!
     532             :                 // Remove it as a workaround
     533           0 :                 aTmp.removeFinalSlash();
     534           0 :             if ( !aTmp.HasError() && aTmp.GetProtocol() != INetProtocol::NotValid )
     535           0 :                 aMatch = aTmp.GetMainURL( INetURLObject::NO_DECODE );
     536             :         }
     537             :     }
     538             :     else
     539             :     {
     540           0 :         OUString aTmpMatch;
     541           0 :         ::utl::LocalFileHelper::ConvertSystemPathToURL( aText, aWorkDir, aTmpMatch );
     542           0 :         aMatch = aTmpMatch;
     543             :     }
     544             : 
     545           0 :     return aMatch;
     546             : }
     547             : 
     548             : 
     549           0 : void SvtMatchContext_Impl::doExecute()
     550             : {
     551           0 :     ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
     552             :     {
     553             :         // have we been stopped while we were waiting for the mutex?
     554           0 :         osl::MutexGuard g(mutex_);
     555           0 :         if (stopped_) {
     556           0 :             return;
     557           0 :         }
     558             :     }
     559             : 
     560             :     // Reset match lists
     561           0 :     aCompletions.clear();
     562           0 :     aURLs.clear();
     563             : 
     564             :     // check for input
     565           0 :     sal_uInt16 nTextLen = aText.getLength();
     566           0 :     if ( !nTextLen )
     567           0 :         return;
     568             : 
     569           0 :     if( aText.indexOf( '*' ) != -1 || aText.indexOf( '?' ) != -1 )
     570             :         // no autocompletion for wildcards
     571           0 :         return;
     572             : 
     573           0 :     OUString aMatch;
     574           0 :     OUString aWorkDir( SvtPathOptions().GetWorkPath() );
     575           0 :     INetProtocol eProt = INetURLObject::CompareProtocolScheme( aText );
     576           0 :     INetProtocol eBaseProt = INetURLObject::CompareProtocolScheme( aBaseURL );
     577           0 :     if ( aBaseURL.isEmpty() )
     578           0 :         eBaseProt = INetURLObject::CompareProtocolScheme( aWorkDir );
     579           0 :     INetProtocol eSmartProt = pBox->GetSmartProtocol();
     580             : 
     581             :     // if the user input is a valid URL, go on with it
     582             :     // otherwise it could be parsed smart with a predefined smart protocol
     583             :     // ( or if this is not set with the protocol of a predefined base URL )
     584           0 :     if( eProt == INetProtocol::NotValid || eProt == eSmartProt || (eSmartProt == INetProtocol::NotValid && eProt == eBaseProt) )
     585             :     {
     586             :         // not stopped yet ?
     587           0 :         if( schedule() )
     588             :         {
     589           0 :             if ( eProt == INetProtocol::NotValid )
     590           0 :                 aMatch = SvtURLBox::ParseSmart( aText, aBaseURL, aWorkDir );
     591             :             else
     592           0 :                 aMatch = aText;
     593           0 :             if ( !aMatch.isEmpty() )
     594             :             {
     595           0 :                 INetURLObject aURLObject( aMatch );
     596           0 :                 OUString aMainURL( aURLObject.GetMainURL( INetURLObject::NO_DECODE ) );
     597             :                 // Disable autocompletion for anything but the (local) file
     598             :                 // system (for which access is hopefully fast), as the logic of
     599             :                 // how SvtMatchContext_Impl is used requires this code to run to
     600             :                 // completion before further user input is processed, and even
     601             :                 // SvtMatchContext_Impl::Stop does not guarantee a speedy
     602             :                 // return:
     603           0 :                 if ( !aMainURL.isEmpty()
     604           0 :                      && aURLObject.GetProtocol() == INetProtocol::File )
     605             :                 {
     606             :                     // if text input is a directory, it must be part of the match list! Until then it is scanned
     607           0 :                     bool folder = false;
     608           0 :                     if (aURLObject.hasFinalSlash()) {
     609             :                         try {
     610             :                             css::uno::Reference< css::uno::XComponentContext >
     611           0 :                                 ctx(comphelper::getProcessComponentContext());
     612             :                             css::uno::Reference<
     613             :                                 css::ucb::XUniversalContentBroker > ucb(
     614             :                                     css::ucb::UniversalContentBroker::create(
     615           0 :                                         ctx));
     616           0 :                             css::uno::Sequence< css::beans::Property > prop(1);
     617           0 :                             prop[0].Name = "IsFolder";
     618           0 :                             prop[0].Handle = -1;
     619           0 :                             prop[0].Type = cppu::UnoType< bool >::get();
     620           0 :                             css::uno::Any res;
     621             :                             css::uno::Reference< css::ucb::XCommandProcessor >
     622             :                                 proc(
     623           0 :                                     ucb->queryContent(
     624           0 :                                         ucb->createContentIdentifier(aMainURL)),
     625           0 :                                     css::uno::UNO_QUERY_THROW);
     626             :                             css::uno::Reference< css::ucb::XCommandProcessor2 >
     627           0 :                                 proc2(proc, css::uno::UNO_QUERY);
     628           0 :                             sal_Int32 id = proc->createCommandIdentifier();
     629             :                             try {
     630             :                                 {
     631           0 :                                     osl::MutexGuard g(mutex_);
     632           0 :                                     processor_ = proc;
     633           0 :                                     commandId_ = id;
     634             :                                 }
     635           0 :                                 res = proc->execute(
     636             :                                     css::ucb::Command(
     637             :                                         "getPropertyValues", -1,
     638             :                                         css::uno::makeAny(prop)),
     639             :                                     id,
     640             :                                     css::uno::Reference<
     641           0 :                                         css::ucb::XCommandEnvironment >());
     642           0 :                             } catch (...) {
     643           0 :                                 if (proc2.is()) {
     644             :                                     try {
     645           0 :                                         proc2->releaseCommandIdentifier(id);
     646           0 :                                     } catch (css::uno::RuntimeException & e) {
     647             :                                         SAL_WARN(
     648             :                                             "svtools.control",
     649             :                                             "ignoring UNO RuntimeException "
     650             :                                             << e.Message);
     651             :                                     }
     652             :                                 }
     653           0 :                                 throw;
     654             :                             }
     655           0 :                             if (proc2.is()) {
     656           0 :                                 proc2->releaseCommandIdentifier(id);
     657             :                             }
     658             :                             {
     659           0 :                                 osl::MutexGuard g(mutex_);
     660           0 :                                 processor_.clear();
     661             :                                 // At least the neon-based WebDAV UCP does not
     662             :                                 // properly support aborting commands, so return
     663             :                                 // anyway now if an abort request had been
     664             :                                 // ignored and the command execution only
     665             :                                 // returned "successfully" after some timeout:
     666           0 :                                 if (stopped_) {
     667           0 :                                     return;
     668           0 :                                 }
     669             :                             }
     670             :                             css::uno::Reference< css::sdbc::XRow > row(
     671           0 :                                 res, css::uno::UNO_QUERY_THROW);
     672           0 :                             folder = row->getBoolean(1) && !row->wasNull();
     673           0 :                         } catch (css::uno::Exception & e) {
     674             :                             SAL_WARN(
     675             :                                 "svtools.control",
     676             :                                 "ignoring UNO Exception " << typeid(*&e).name()
     677             :                                 << ": " << e.Message);
     678           0 :                             return;
     679             :                         }
     680             :                     }
     681           0 :                     if ( folder )
     682           0 :                             Insert( aText, aMatch );
     683             :                     else
     684             :                         // otherwise the parent folder will be taken
     685           0 :                         aURLObject.removeSegment();
     686             : 
     687             :                     // scan directory and insert all matches
     688           0 :                     ReadFolder( aURLObject.GetMainURL( INetURLObject::NO_DECODE ), aMatch, eProt == INetProtocol::NotValid );
     689           0 :                 }
     690             :             }
     691             :         }
     692             :     }
     693             : 
     694           0 :     if ( bOnlyDirectories )
     695             :         // don't scan history picklist if only directories are allowed, picklist contains only files
     696           0 :         return;
     697             : 
     698           0 :     bool bFull = false;
     699             : 
     700           0 :     INetURLObject aCurObj;
     701           0 :     OUString aEmpty, aCurString, aCurMainURL;
     702           0 :     INetURLObject aObj;
     703           0 :     aObj.SetSmartProtocol( eSmartProt == INetProtocol::NotValid ? INetProtocol::Http : eSmartProt );
     704             :     for( ;; )
     705             :     {
     706           0 :         for(std::vector<OUString>::iterator i = aPickList.begin(); schedule() && i != aPickList.end(); ++i)
     707             :         {
     708           0 :             aCurObj.SetURL(*i);
     709           0 :             aCurObj.SetSmartURL( aCurObj.GetURLNoPass());
     710           0 :             aCurMainURL = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
     711             : 
     712           0 :             if( eProt != INetProtocol::NotValid && aCurObj.GetProtocol() != eProt )
     713           0 :                 continue;
     714             : 
     715           0 :             if( eSmartProt != INetProtocol::NotValid && aCurObj.GetProtocol() != eSmartProt )
     716           0 :                 continue;
     717             : 
     718           0 :             switch( aCurObj.GetProtocol() )
     719             :             {
     720             :                 case INetProtocol::Http:
     721             :                 case INetProtocol::Https:
     722             :                 case INetProtocol::Ftp:
     723             :                 {
     724           0 :                     if( eProt == INetProtocol::NotValid && !bFull )
     725             :                     {
     726           0 :                         aObj.SetSmartURL( aText );
     727           0 :                         if( aObj.GetURLPath().getLength() > 1 )
     728           0 :                             continue;
     729             :                     }
     730             : 
     731           0 :                     aCurString = aCurMainURL;
     732           0 :                     if( eProt == INetProtocol::NotValid )
     733             :                     {
     734             :                         // try if text matches the scheme
     735           0 :                         OUString aScheme( INetURLObject::GetScheme( aCurObj.GetProtocol() ) );
     736           0 :                         if ( aScheme.startsWithIgnoreAsciiCase( aText ) && aText.getLength() < aScheme.getLength() )
     737             :                         {
     738           0 :                             if( bFull )
     739           0 :                                 aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
     740             :                             else
     741             :                             {
     742           0 :                                 aCurObj.SetMark( aEmpty );
     743           0 :                                 aCurObj.SetParam( aEmpty );
     744           0 :                                 aCurObj.SetURLPath( aEmpty );
     745           0 :                                 aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
     746             :                             }
     747             : 
     748           0 :                             Insert( aMatch, aMatch );
     749             :                         }
     750             : 
     751             :                         // now try smart matching
     752           0 :                         aCurString = aCurString.copy( aScheme.getLength() );
     753             :                     }
     754             : 
     755           0 :                     if( aCurString.startsWithIgnoreAsciiCase( aText ) )
     756             :                     {
     757           0 :                         if( bFull )
     758           0 :                             aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
     759             :                         else
     760             :                         {
     761           0 :                             aCurObj.SetMark( aEmpty );
     762           0 :                             aCurObj.SetParam( aEmpty );
     763           0 :                             aCurObj.SetURLPath( aEmpty );
     764           0 :                             aMatch = aCurObj.GetMainURL( INetURLObject::NO_DECODE );
     765             :                         }
     766             : 
     767           0 :                         OUString aURL( aMatch );
     768           0 :                         if( eProt == INetProtocol::NotValid )
     769           0 :                             aMatch = aMatch.copy( INetURLObject::GetScheme( aCurObj.GetProtocol() ).getLength() );
     770             : 
     771           0 :                         if( aText.getLength() < aMatch.getLength() )
     772           0 :                             Insert( aMatch, aURL );
     773             : 
     774           0 :                         continue;
     775             :                     }
     776           0 :                     break;
     777             :                 }
     778             :                 default:
     779             :                 {
     780           0 :                     if( bFull )
     781           0 :                         continue;
     782             : 
     783           0 :                     if( aCurMainURL.startsWith(aText) )
     784             :                     {
     785           0 :                         if( aText.getLength() < aCurMainURL.getLength() )
     786           0 :                             Insert( aCurMainURL, aCurMainURL );
     787             : 
     788           0 :                         continue;
     789             :                     }
     790           0 :                     break;
     791             :                 }
     792             :             }
     793             :         }
     794             : 
     795           0 :         if( !bFull )
     796           0 :             bFull = true;
     797             :         else
     798           0 :             break;
     799           0 :     }
     800             : 
     801           0 :     return;
     802             : }
     803             : 
     804           0 : void SvtURLBox::TryAutoComplete()
     805             : {
     806           0 :     if( Application::AnyInput( VclInputFlags::KEYBOARD ) ) return;
     807             : 
     808           0 :     OUString aCurText = GetText();
     809           0 :     Selection aSelection( GetSelection() );
     810           0 :     if( aSelection.Max() != aCurText.getLength() )
     811           0 :         return;
     812           0 :     sal_uInt16 nLen = (sal_uInt16)aSelection.Min();
     813           0 :     aCurText = aCurText.copy( 0, nLen );
     814           0 :     if( !aCurText.isEmpty() && bIsAutoCompleteEnabled )
     815             :     {
     816           0 :         if ( pCtx.is() )
     817             :         {
     818           0 :             pCtx->Stop();
     819           0 :             pCtx->join();
     820           0 :             pCtx.clear();
     821             :         }
     822           0 :         pCtx = new SvtMatchContext_Impl( this, aCurText );
     823           0 :         pCtx->launch();
     824           0 :     }
     825             : }
     826             : 
     827             : 
     828           0 : SvtURLBox::SvtURLBox( vcl::Window* pParent, INetProtocol eSmart, bool bSetDefaultHelpID )
     829             :     :   ComboBox( pParent , WB_DROPDOWN | WB_AUTOSIZE | WB_AUTOHSCROLL ),
     830             :         eSmartProtocol( eSmart ),
     831             :         bAutoCompleteMode( false ),
     832             :         bOnlyDirectories( false ),
     833             :         bCtrlClick( false ),
     834             :         bHistoryDisabled( false ),
     835             :         bNoSelection( false ),
     836           0 :         bIsAutoCompleteEnabled( true )
     837             : {
     838           0 :     Init(bSetDefaultHelpID);
     839             : 
     840           0 :     if ( GetDesktopRectPixel().GetWidth() > 800 )
     841           0 :         SetSizePixel( Size( 300, 240 ) );
     842             :     else
     843           0 :         SetSizePixel( Size( 225, 240 ) );
     844           0 : }
     845             : 
     846             : 
     847           0 : SvtURLBox::SvtURLBox( vcl::Window* pParent, WinBits _nStyle, INetProtocol eSmart,
     848             :     bool bSetDefaultHelpID )
     849             :     :   ComboBox( pParent, _nStyle ),
     850             :         eSmartProtocol( eSmart ),
     851             :         bAutoCompleteMode( false ),
     852             :         bOnlyDirectories( false ),
     853             :         bCtrlClick( false ),
     854             :         bHistoryDisabled( false ),
     855             :         bNoSelection( false ),
     856           0 :         bIsAutoCompleteEnabled( true )
     857             : {
     858           0 :     Init(bSetDefaultHelpID);
     859           0 : }
     860             : 
     861           0 : VCL_BUILDER_DECL_FACTORY(SvtURLBox)
     862             : {
     863             :     (void)rMap;
     864             :     WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP|
     865           0 :                        WB_DROPDOWN|WB_AUTOSIZE|WB_AUTOHSCROLL;
     866           0 :     VclPtrInstance<SvtURLBox> pListBox(pParent, nWinBits, INetProtocol::NotValid, false);
     867           0 :     pListBox->EnableAutoSize(true);
     868           0 :     rRet = pListBox;
     869           0 : }
     870             : 
     871             : 
     872           0 : SvtURLBox::SvtURLBox( vcl::Window* pParent, const ResId& _rResId, INetProtocol eSmart,
     873             :     bool bSetDefaultHelpID )
     874             :     :   ComboBox( pParent , _rResId ),
     875             :         eSmartProtocol( eSmart ),
     876             :         bAutoCompleteMode( false ),
     877             :         bOnlyDirectories( false ),
     878             :         bCtrlClick( false ),
     879             :         bHistoryDisabled( false ),
     880             :         bNoSelection( false ),
     881           0 :         bIsAutoCompleteEnabled( true )
     882             : {
     883           0 :     Init(bSetDefaultHelpID);
     884           0 : }
     885             : 
     886           0 : void SvtURLBox::Init(bool bSetDefaultHelpID)
     887             : {
     888           0 :     pImp = new SvtURLBox_Impl();
     889             : 
     890           0 :     if (bSetDefaultHelpID && GetHelpId().isEmpty())
     891           0 :         SetHelpId( ".uno:OpenURL" );
     892           0 :     EnableAutocomplete( false );
     893             : 
     894           0 :     SetText( OUString() );
     895             : 
     896           0 :     GetSubEdit()->autocompleteSignal.connect( boost::bind( &SvtURLBox::AutoCompleteHandler, this, _1 ) );
     897           0 :     UpdatePicklistForSmartProtocol_Impl();
     898             : 
     899           0 :     EnableAutoSize(GetStyle() & WB_AUTOSIZE);
     900           0 : }
     901             : 
     902           0 : SvtURLBox::~SvtURLBox()
     903             : {
     904           0 :     disposeOnce();
     905           0 : }
     906             : 
     907           0 : void SvtURLBox::dispose()
     908             : {
     909           0 :     if( pCtx.is() )
     910             :     {
     911           0 :         pCtx->Stop();
     912           0 :         pCtx->join();
     913             :     }
     914             : 
     915           0 :     delete pImp;
     916           0 :     ComboBox::dispose();
     917           0 : }
     918             : 
     919           0 : void SvtURLBox::UpdatePickList( )
     920             : {
     921           0 :     if( pCtx.is() )
     922             :     {
     923           0 :         pCtx->Stop();
     924           0 :         pCtx->join();
     925           0 :         pCtx.clear();
     926             :     }
     927             : 
     928           0 :     OUString sText = GetText();
     929           0 :     if ( !sText.isEmpty() && bIsAutoCompleteEnabled )
     930             :     {
     931           0 :         pCtx = new SvtMatchContext_Impl( this, sText );
     932           0 :         pCtx->launch();
     933           0 :     }
     934           0 : }
     935             : 
     936           0 : void SvtURLBox::SetSmartProtocol( INetProtocol eProt )
     937             : {
     938           0 :     if ( eSmartProtocol != eProt )
     939             :     {
     940           0 :         eSmartProtocol = eProt;
     941           0 :         UpdatePicklistForSmartProtocol_Impl();
     942             :     }
     943           0 : }
     944             : 
     945           0 : void SvtURLBox::UpdatePicklistForSmartProtocol_Impl()
     946             : {
     947           0 :     Clear();
     948           0 :     if ( !bHistoryDisabled )
     949             :     {
     950             :         // read history pick list
     951           0 :         Sequence< Sequence< PropertyValue > > seqPicklist = SvtHistoryOptions().GetList( ePICKLIST );
     952           0 :         sal_uInt32 nCount = seqPicklist.getLength();
     953           0 :         INetURLObject aCurObj;
     954             : 
     955           0 :         for( sal_uInt32 nItem=0; nItem < nCount; nItem++ )
     956             :         {
     957           0 :             Sequence< PropertyValue > seqPropertySet = seqPicklist[ nItem ];
     958             : 
     959           0 :             OUString sURL;
     960             : 
     961           0 :             sal_uInt32 nPropertyCount = seqPropertySet.getLength();
     962             : 
     963           0 :             for( sal_uInt32 nProperty=0; nProperty < nPropertyCount; nProperty++ )
     964             :             {
     965           0 :                 if( seqPropertySet[nProperty].Name == HISTORY_PROPERTYNAME_URL )
     966             :                 {
     967           0 :                     seqPropertySet[nProperty].Value >>= sURL;
     968           0 :                     aCurObj.SetURL( sURL );
     969             : 
     970           0 :                     if ( !sURL.isEmpty() && ( eSmartProtocol != INetProtocol::NotValid ) )
     971             :                     {
     972           0 :                         if( aCurObj.GetProtocol() != eSmartProtocol )
     973           0 :                             break;
     974             :                     }
     975             : 
     976           0 :                     OUString aURL( aCurObj.GetMainURL( INetURLObject::DECODE_WITH_CHARSET ) );
     977             : 
     978           0 :                     if ( !aURL.isEmpty() )
     979             :                     {
     980           0 :                         bool bFound = aURL.endsWith("/");
     981           0 :                         if ( !bFound )
     982             :                         {
     983           0 :                             OUString aUpperURL( aURL );
     984           0 :                             aUpperURL = aUpperURL.toAsciiUpperCase();
     985             : 
     986             :                             bFound = ::std::any_of(pImp->m_aFilters.begin(),
     987             :                                                    pImp->m_aFilters.end(),
     988           0 :                                                    FilterMatch( aUpperURL ) );
     989             :                         }
     990           0 :                         if ( bFound )
     991             :                         {
     992           0 :                             OUString aFile;
     993           0 :                             if (::utl::LocalFileHelper::ConvertURLToSystemPath(aURL,aFile))
     994           0 :                                 InsertEntry(aFile);
     995             :                             else
     996           0 :                                 InsertEntry(aURL);
     997             :                         }
     998             :                     }
     999           0 :                     break;
    1000             :                 }
    1001             :             }
    1002           0 :         }
    1003             :     }
    1004           0 : }
    1005             : 
    1006             : 
    1007           0 : bool SvtURLBox::ProcessKey( const vcl::KeyCode& rKey )
    1008             : {
    1009             :     // every key input stops the current matching thread
    1010           0 :     if( pCtx.is() )
    1011             :     {
    1012           0 :         pCtx->Stop();
    1013           0 :         pCtx->join();
    1014           0 :         pCtx.clear();
    1015             :     }
    1016             : 
    1017           0 :     vcl::KeyCode aCode( rKey.GetCode() );
    1018           0 :     if ( aCode == KEY_RETURN && !GetText().isEmpty() )
    1019             :     {
    1020             :         // wait for completion of matching thread
    1021           0 :         ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
    1022             : 
    1023           0 :         if ( bAutoCompleteMode )
    1024             :         {
    1025             :             // reset picklist
    1026           0 :             bAutoCompleteMode = false;
    1027           0 :             Selection aSelection( GetSelection() );
    1028           0 :             SetSelection( Selection( aSelection.Min(), aSelection.Min() ) );
    1029           0 :             if ( bOnlyDirectories )
    1030           0 :                 Clear();
    1031             :             else
    1032           0 :                 UpdatePicklistForSmartProtocol_Impl();
    1033           0 :             Resize();
    1034             :         }
    1035             : 
    1036           0 :         bCtrlClick = rKey.IsMod1();
    1037           0 :         bool bHandled = false;
    1038           0 :         if ( GetOpenHdl().IsSet() )
    1039             :         {
    1040           0 :             bHandled = true;
    1041           0 :             GetOpenHdl().Call(this);
    1042             :         }
    1043           0 :         else if ( GetSelectHdl().IsSet() )
    1044             :         {
    1045           0 :             bHandled = true;
    1046           0 :             GetSelectHdl().Call(this);
    1047             :         }
    1048             : 
    1049           0 :         bCtrlClick = false;
    1050             : 
    1051           0 :         ClearModifyFlag();
    1052           0 :         return bHandled;
    1053             :     }
    1054           0 :     else if ( aCode == KEY_RETURN && GetText().isEmpty() && GetOpenHdl().IsSet() )
    1055             :     {
    1056             :         // for file dialog
    1057           0 :         bAutoCompleteMode = false;
    1058           0 :         GetOpenHdl().Call(this);
    1059           0 :         return true;
    1060             :     }
    1061           0 :     else if( aCode == KEY_ESCAPE )
    1062             :     {
    1063           0 :         Selection aSelection( GetSelection() );
    1064           0 :         if ( bAutoCompleteMode || aSelection.Min() != aSelection.Max() )
    1065             :         {
    1066           0 :             SetSelection( Selection( aSelection.Min(), aSelection.Min() ) );
    1067           0 :             if ( bOnlyDirectories )
    1068           0 :                 Clear();
    1069             :             else
    1070           0 :                 UpdatePicklistForSmartProtocol_Impl();
    1071           0 :             Resize();
    1072             :         }
    1073             :         else
    1074             :         {
    1075           0 :            return false;
    1076             :         }
    1077             : 
    1078           0 :         bAutoCompleteMode = false;
    1079           0 :         return true;
    1080             :     }
    1081             :     else
    1082             :     {
    1083           0 :         return false;
    1084             :     }
    1085             : }
    1086             : 
    1087             : 
    1088           0 : void SvtURLBox::Modify()
    1089             : {
    1090           0 :     ComboBox::Modify();
    1091           0 : }
    1092             : 
    1093             : 
    1094           0 : bool SvtURLBox::PreNotify( NotifyEvent& rNEvt )
    1095             : {
    1096           0 :     if( rNEvt.GetWindow() == GetSubEdit() && rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
    1097             :     {
    1098             : 
    1099           0 :         const KeyEvent& rEvent = *rNEvt.GetKeyEvent();
    1100           0 :         const vcl::KeyCode& rKey = rEvent.GetKeyCode();
    1101           0 :         vcl::KeyCode aCode( rKey.GetCode() );
    1102           0 :         if( ProcessKey( rKey ) )
    1103             :         {
    1104           0 :             return true;
    1105             :         }
    1106           0 :         else if( ( aCode == KEY_UP || aCode == KEY_DOWN ) && !rKey.IsMod2() )
    1107             :         {
    1108           0 :             Selection aSelection( GetSelection() );
    1109           0 :             sal_uInt16 nLen = (sal_uInt16)aSelection.Min();
    1110           0 :             GetSubEdit()->KeyInput( rEvent );
    1111           0 :             SetSelection( Selection( nLen, GetText().getLength() ) );
    1112           0 :             return true;
    1113             :         }
    1114             : 
    1115           0 :         if ( MatchesPlaceHolder( GetText() ) )
    1116             :         {
    1117             :             // set the selection so a key stroke will overwrite
    1118             :             // the placeholder rather than edit it
    1119           0 :             SetSelection( Selection( 0, GetText().getLength() ) );
    1120             :         }
    1121             :     }
    1122             : 
    1123           0 :     return ComboBox::PreNotify( rNEvt );
    1124             : }
    1125             : 
    1126             : 
    1127           0 : void SvtURLBox::AutoCompleteHandler( Edit* )
    1128             : {
    1129           0 :     if ( GetSubEdit()->GetAutocompleteAction() == AUTOCOMPLETE_KEYINPUT )
    1130           0 :         TryAutoComplete();
    1131           0 : }
    1132             : 
    1133             : 
    1134           0 : bool SvtURLBox::Notify( NotifyEvent &rEvt )
    1135             : {
    1136           0 :     if ( MouseNotifyEvent::GETFOCUS == rEvt.GetType() )
    1137             :     {
    1138             : #ifndef UNX
    1139             :         // pb: don't select automatically on unix #93251#
    1140             :         SetSelection( Selection( 0, GetText().getLength() ) );
    1141             : #endif
    1142             :     }
    1143           0 :     else if ( MouseNotifyEvent::LOSEFOCUS == rEvt.GetType() )
    1144             :     {
    1145           0 :         if( GetText().isEmpty() )
    1146           0 :             ClearModifyFlag();
    1147           0 :         if ( pCtx.is() )
    1148             :         {
    1149           0 :             pCtx->Stop();
    1150           0 :             pCtx->join();
    1151           0 :             pCtx.clear();
    1152             :         }
    1153             :     }
    1154             : 
    1155           0 :     return ComboBox::Notify( rEvt );
    1156             : }
    1157             : 
    1158             : 
    1159           0 : void SvtURLBox::Select()
    1160             : {
    1161           0 :     ComboBox::Select();
    1162           0 :     ClearModifyFlag();
    1163           0 : }
    1164             : 
    1165             : 
    1166           0 : void SvtURLBox::SetOnlyDirectories( bool bDir )
    1167             : {
    1168           0 :     bOnlyDirectories = bDir;
    1169           0 :     if ( bOnlyDirectories )
    1170           0 :         Clear();
    1171           0 : }
    1172             : 
    1173             : 
    1174           0 : void SvtURLBox::SetNoURLSelection( bool bSet )
    1175             : {
    1176           0 :     bNoSelection = bSet;
    1177           0 : }
    1178             : 
    1179             : 
    1180           0 : OUString SvtURLBox::GetURL()
    1181             : {
    1182             :     // wait for end of autocompletion
    1183           0 :     ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
    1184             : 
    1185           0 :     OUString aText( GetText() );
    1186           0 :     if ( MatchesPlaceHolder( aText ) )
    1187           0 :         return aPlaceHolder;
    1188             : 
    1189             :     // try to get the right case preserving URL from the list of URLs
    1190           0 :     for(std::vector<OUString>::iterator i = pImp->aCompletions.begin(), j = pImp->aURLs.begin(); i != pImp->aCompletions.end() && j != pImp->aURLs.end(); ++i, ++j)
    1191             :     {
    1192           0 :         if((*i).equals(aText))
    1193           0 :             return *j;
    1194             :     }
    1195             : 
    1196             : #ifdef WNT
    1197             :     // erase trailing spaces on Windows since thay are invalid on this OS and
    1198             :     // most of the time they are inserted by accident via copy / paste
    1199             :     aText = comphelper::string::stripEnd(aText, ' ');
    1200             :     if ( aText.isEmpty() )
    1201             :         return aText;
    1202             :     // #i9739#
    1203             : #endif
    1204             : 
    1205           0 :     INetURLObject aObj( aText );
    1206           0 :     if( aText.indexOf( '*' ) != -1 || aText.indexOf( '?' ) != -1 )
    1207             :     {
    1208             :         // no autocompletion for wildcards
    1209           0 :         INetURLObject aTempObj;
    1210           0 :         if ( eSmartProtocol != INetProtocol::NotValid )
    1211           0 :             aTempObj.SetSmartProtocol( eSmartProtocol );
    1212           0 :         if ( aTempObj.SetSmartURL( aText ) )
    1213           0 :             return aTempObj.GetMainURL( INetURLObject::NO_DECODE );
    1214             :         else
    1215           0 :             return aText;
    1216             :     }
    1217             : 
    1218           0 :     if ( aObj.GetProtocol() == INetProtocol::NotValid )
    1219             :     {
    1220           0 :         OUString aName = ParseSmart( aText, aBaseURL, SvtPathOptions().GetWorkPath() );
    1221           0 :         aObj.SetURL(aName);
    1222           0 :         OUString aURL( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
    1223           0 :         if ( aURL.isEmpty() )
    1224             :             // aText itself is invalid, and even together with aBaseURL, it could not
    1225             :             // made valid -> no chance
    1226           0 :             return aText;
    1227             : 
    1228           0 :         bool bSlash = aObj.hasFinalSlash();
    1229             :         {
    1230           0 :             const OUString aPropName("CasePreservingURL");
    1231             : 
    1232           0 :             OUString aFileURL;
    1233             : 
    1234           0 :             Any aAny = UCBContentHelper::GetProperty(aURL, aPropName);
    1235           0 :             bool success = (aAny >>= aFileURL);
    1236           0 :             OUString aTitle;
    1237           0 :             if(success)
    1238           0 :                 aTitle = INetURLObject(aFileURL).getName(
    1239             :                              INetURLObject::LAST_SEGMENT,
    1240             :                              true,
    1241           0 :                              INetURLObject::DECODE_WITH_CHARSET );
    1242             :             else
    1243             :                 success =
    1244           0 :                     UCBContentHelper::GetTitle(aURL,&aTitle);
    1245             : 
    1246           0 :             if( success && aTitle != "/" && aTitle != "." )
    1247             :             {
    1248           0 :                     aObj.SetName( aTitle );
    1249           0 :                     if ( bSlash )
    1250           0 :                         aObj.setFinalSlash();
    1251           0 :             }
    1252           0 :         }
    1253             :     }
    1254             : 
    1255           0 :     return aObj.GetMainURL( INetURLObject::NO_DECODE );
    1256             : }
    1257             : 
    1258           0 : void SvtURLBox::DisableHistory()
    1259             : {
    1260           0 :     bHistoryDisabled = true;
    1261           0 :     UpdatePicklistForSmartProtocol_Impl();
    1262           0 : }
    1263             : 
    1264           0 : void SvtURLBox::SetBaseURL( const OUString& rURL )
    1265             : {
    1266           0 :     ::osl::MutexGuard aGuard( theSvtMatchContextMutex::get() );
    1267             : 
    1268             :     // Reset match lists
    1269           0 :     pImp->aCompletions.clear();
    1270           0 :     pImp->aURLs.clear();
    1271             : 
    1272           0 :     aBaseURL = rURL;
    1273           0 : }
    1274             : 
    1275             : /** Parse leading ~ for Unix systems,
    1276             :     does nothing for Windows
    1277             :  */
    1278           0 : bool SvtURLBox_Impl::TildeParsing(
    1279             :     OUString&
    1280             : #ifdef UNX
    1281             :     aText
    1282             : #endif
    1283             :     , OUString&
    1284             : #ifdef UNX
    1285             :     aBaseURL
    1286             : #endif
    1287             : )
    1288             : {
    1289             : #ifdef UNX
    1290           0 :     if( aText.startsWith( "~" ) )
    1291             :     {
    1292           0 :         OUString aParseTilde;
    1293           0 :         bool bTrailingSlash = true; // use trailing slash
    1294             : 
    1295           0 :         if( aText.getLength() == 1 || aText[ 1 ] == '/' )
    1296             :         {
    1297             :             // covers "~" or "~/..." cases
    1298           0 :             const char* aHomeLocation = getenv( "HOME" );
    1299           0 :             if( !aHomeLocation )
    1300           0 :                 aHomeLocation = "";
    1301             : 
    1302           0 :             aParseTilde = OUString::createFromAscii(aHomeLocation);
    1303             : 
    1304             :             // in case the whole path is just "~" then there should
    1305             :             // be no trailing slash at the end
    1306           0 :             if( aText.getLength() == 1 )
    1307           0 :                 bTrailingSlash = false;
    1308             :         }
    1309             :         else
    1310             :         {
    1311             :             // covers "~username" and "~username/..." cases
    1312           0 :             sal_Int32 nNameEnd = aText.indexOf( '/' );
    1313           0 :             OUString aUserName = aText.copy( 1, ( nNameEnd != -1 ) ? nNameEnd : ( aText.getLength() - 1 ) );
    1314             : 
    1315           0 :             struct passwd* pPasswd = NULL;
    1316             : #ifdef SOLARIS
    1317             :             Sequence< sal_Int8 > sBuf( 1024 );
    1318             :             struct passwd aTmp;
    1319             :             sal_Int32 nRes = getpwnam_r( OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US ).getStr(),
    1320             :                                   &aTmp,
    1321             :                                   (char*)sBuf.getArray(),
    1322             :                                   1024,
    1323             :                                   &pPasswd );
    1324             :             if( !nRes && pPasswd )
    1325             :                 aParseTilde = OUString::createFromAscii(pPasswd->pw_dir);
    1326             :             else
    1327             :                 return false; // no such user
    1328             : #else
    1329           0 :             pPasswd = getpwnam( OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US ).getStr() );
    1330           0 :             if( pPasswd )
    1331           0 :                 aParseTilde = OUString::createFromAscii(pPasswd->pw_dir);
    1332             :             else
    1333           0 :                 return false; // no such user
    1334             : #endif
    1335             : 
    1336             :             // in case the path is "~username" then there should
    1337             :             // be no trailing slash at the end
    1338           0 :             if( nNameEnd == -1 )
    1339           0 :                 bTrailingSlash = false;
    1340             :         }
    1341             : 
    1342           0 :         if( !bTrailingSlash )
    1343             :         {
    1344           0 :             if( aParseTilde.isEmpty() || aParseTilde == "/" )
    1345             :             {
    1346             :                 // "/" path should be converted to "/."
    1347           0 :                 aParseTilde = "/.";
    1348             :             }
    1349             :             else
    1350             :             {
    1351             :                 // "blabla/" path should be converted to "blabla"
    1352           0 :                 aParseTilde = comphelper::string::stripEnd(aParseTilde, '/');
    1353             :             }
    1354             :         }
    1355             :         else
    1356             :         {
    1357           0 :             if( !aParseTilde.endsWith("/") )
    1358           0 :                 aParseTilde += "/";
    1359           0 :             if( aText.getLength() > 2 )
    1360           0 :                 aParseTilde += aText.copy( 2 );
    1361             :         }
    1362             : 
    1363           0 :         aText = aParseTilde;
    1364           0 :         aBaseURL.clear(); // tilde provide absolute path
    1365             :     }
    1366             : #endif
    1367             : 
    1368           0 :     return true;
    1369             : }
    1370             : 
    1371           0 : void SvtURLBox::SetFilter(const OUString& _sFilter)
    1372             : {
    1373           0 :     pImp->m_aFilters.clear();
    1374           0 :     FilterMatch::createWildCardFilterList(_sFilter,pImp->m_aFilters);
    1375         798 : }
    1376             : 
    1377             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11