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