1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 //-----------------------------------------------------------------------------
25 // includes
26 //-----------------------------------------------------------------------------
27 
28 #include "VistaFilePickerImpl.hxx"
29 
30 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
31 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
32 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
33 #include <com/sun/star/beans/StringPair.hpp>
34 #include <comphelper/sequenceasvector.hxx>
35 #include <osl/file.hxx>
36 #include <osl/mutex.hxx>
37 #ifdef __MINGW32__
38 #include <limits.h>
39 #endif
40 #include "..\misc\WinImplHelper.hxx"
41 
42 #include <Shlguid.h>
43 
is_current_process_window(HWND hwnd)44  inline bool is_current_process_window(HWND hwnd)
45 {
46     DWORD pid;
47     GetWindowThreadProcessId(hwnd, &pid);
48     return (pid == GetCurrentProcessId());
49 }
50 
choose_parent_window()51 HWND choose_parent_window()
52 {
53     HWND hwnd_parent = GetForegroundWindow();
54     if (!is_current_process_window(hwnd_parent))
55        hwnd_parent = GetDesktopWindow();
56     return hwnd_parent;
57 }
58 
59 //-----------------------------------------------------------------------------
60 // namespace
61 //-----------------------------------------------------------------------------
62 
63 namespace fpicker{
64 namespace win32{
65 namespace vista{
66 
67 namespace css = ::com::sun::star;
68 
69 //-----------------------------------------------------------------------------
70 // types, const etcpp.
71 //-----------------------------------------------------------------------------
72 
73 
74 static const ::sal_Int16 INVALID_CONTROL_ID     = -1;
75 static const ::sal_Int16 INVALID_CONTROL_ACTION = -1;
76 
77 typedef ::comphelper::SequenceAsVector< ::rtl::OUString > TStringList;
78 
79 // Guids used for IFileDialog::SetClientGuid
80 static const GUID CLIENTID_FILEDIALOG_SIMPLE		= {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83};
81 static const GUID CLIENTID_FILEDIALOG_OPTIONS		= {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36};
82 static const GUID CLIENTID_FILESAVE					= {0x3B2E2261, 0x402D, 0x4049, 0xB0, 0xC0, 0x91, 0x13, 0xF8, 0x6E, 0x84, 0x7C};
83 static const GUID CLIENTID_FILESAVE_PASSWORD		= {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6};
84 static const GUID CLIENTID_FILESAVE_SELECTION		= {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE};
85 static const GUID CLIENTID_FILESAVE_TEMPLATE		= {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE};
86 static const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE	= {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C};
87 static const GUID CLIENTID_FILEOPEN_PLAY			= {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5};
88 static const GUID CLIENTID_FILEOPEN_LINK			= {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A};
89 
90 //-----------------------------------------------------------------------------
lcl_getURLFromShellItem(IShellItem * pItem)91 ::rtl::OUString lcl_getURLFromShellItem (IShellItem* pItem)
92 {
93     LPOLESTR pStr = NULL;
94 	::rtl::OUString sURL;
95 
96 	SIGDN   eConversion = SIGDN_FILESYSPATH;
97     HRESULT hr          = pItem->GetDisplayName ( eConversion, &pStr );
98 
99     if ( FAILED(hr) )
100 	{
101 		eConversion = SIGDN_URL;
102 		hr          = pItem->GetDisplayName ( eConversion, &pStr );
103 
104 		if ( FAILED(hr) )
105 			return ::rtl::OUString();
106 
107 		sURL = ::rtl::OUString(reinterpret_cast<sal_Unicode*>(pStr));
108 	}
109 	else
110 	{
111 		::osl::FileBase::getFileURLFromSystemPath( reinterpret_cast<sal_Unicode*>(pStr), sURL );
112 	}
113 
114     CoTaskMemFree (pStr);
115     return sURL;
116 }
117 
118 //-----------------------------------------------------------------------------------------
lcl_buildFilterList(CFilterContainer & rContainer)119 ::std::vector< COMDLG_FILTERSPEC > lcl_buildFilterList(CFilterContainer& rContainer)
120 {
121     const sal_Int32                          c      = rContainer.numFilter();
122           sal_Int32                          i      = 0;
123           ::std::vector< COMDLG_FILTERSPEC > lList  ;
124           CFilterContainer::FILTER_ENTRY_T   aFilter;
125 
126     rContainer.beginEnumFilter( );
127 	while( rContainer.getNextFilter(aFilter) )
128     {
129         COMDLG_FILTERSPEC aSpec;
130 
131 		aSpec.pszName = reinterpret_cast<LPCTSTR>(aFilter.first.getStr()) ;
132 		aSpec.pszSpec = reinterpret_cast<LPCTSTR>(aFilter.second.getStr());
133 
134         lList.push_back(aSpec);
135     }
136 
137     return lList;
138 }
139 
140 //-----------------------------------------------------------------------------------------
VistaFilePickerImpl()141 VistaFilePickerImpl::VistaFilePickerImpl()
142     : m_iDialogOpen  ()
143     , m_iDialogSave  ()
144     , m_hLastResult  ()
145     , m_lFilters     ()
146     , m_lLastFiles   ()
147     , m_iEventHandler(new VistaFilePickerEventHandler(this))
148     , m_bInExecute   (sal_False)
149     , m_bWasExecuted (sal_False)
150 	, m_sDirectory   ()
151 	, m_sFilename    ()
152 {
153 	m_hParentWindow = choose_parent_window();
154 }
155 
156 //-------------------------------------------------------------------------------
~VistaFilePickerImpl()157 VistaFilePickerImpl::~VistaFilePickerImpl()
158 {
159 }
160 
161 //-------------------------------------------------------------------------------
before()162 void VistaFilePickerImpl::before()
163 {
164     // SYNCHRONIZED->
165     ::osl::ResettableMutexGuard aLock(m_aMutex);
166 
167     // TRICKY .-)
168     // osl::Thread class initializes COm already in MTA mode because it's needed
169     // by VCL and UNO so. There is no way to change that from outside ...
170     // but we need a STA environment ...
171     // So we make it by try-and-error ...
172     // If first CoInitialize will fail .. we unitialize COM initialize it new .-)
173 
174     m_hLastResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
175     if ( FAILED(m_hLastResult) )
176     {
177         CoUninitialize();
178         m_hLastResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
179     }
180 }
181 
182 //-------------------------------------------------------------------------------
doRequest(const RequestRef & rRequest)183 void VistaFilePickerImpl::doRequest(const RequestRef& rRequest)
184 {
185     try
186     {
187         switch(rRequest->getRequest())
188         {
189             case E_ADD_PICKER_LISTENER :
190                     impl_sta_addFilePickerListener(rRequest);
191                     break;
192 
193             case E_REMOVE_PICKER_LISTENER :
194                     impl_sta_removeFilePickerListener(rRequest);
195                     break;
196 
197             case E_APPEND_FILTER :
198                     impl_sta_appendFilter(rRequest);
199                     break;
200 
201 			case E_APPEND_FILTERGROUP :
202 					impl_sta_appendFilterGroup(rRequest);
203 					break;
204 
205 			case E_SET_CURRENT_FILTER :
206                     impl_sta_setCurrentFilter(rRequest);
207                     break;
208 
209             case E_GET_CURRENT_FILTER :
210                     impl_sta_getCurrentFilter(rRequest);
211                     break;
212 
213             case E_CREATE_OPEN_DIALOG :
214                     impl_sta_CreateOpenDialog(rRequest);
215                     break;
216 
217             case E_CREATE_SAVE_DIALOG :
218                     impl_sta_CreateSaveDialog(rRequest);
219                     break;
220 
221             case E_SET_MULTISELECTION_MODE :
222                     impl_sta_SetMultiSelectionMode(rRequest);
223                     break;
224 
225             case E_SET_TITLE :
226                     impl_sta_SetTitle(rRequest);
227                     break;
228 
229 			case E_SET_FILENAME:
230 				impl_sta_SetFileName(rRequest);
231 				break;
232 
233             case E_SET_DIRECTORY :
234                     impl_sta_SetDirectory(rRequest);
235                     break;
236 
237 			case E_GET_DIRECTORY :
238 					impl_sta_GetDirectory(rRequest);
239 					break;
240 
241 			case E_SET_DEFAULT_NAME :
242 					impl_sta_SetDefaultName(rRequest);
243 					break;
244 
245             case E_GET_SELECTED_FILES :
246                     impl_sta_getSelectedFiles(rRequest);
247                     break;
248 
249             case E_SHOW_DIALOG_MODAL :
250                     impl_sta_ShowDialogModal(rRequest);
251                     break;
252 
253             case E_SET_CONTROL_VALUE :
254                     impl_sta_SetControlValue(rRequest);
255                     break;
256 
257             case E_GET_CONTROL_VALUE :
258                     impl_sta_GetControlValue(rRequest);
259                     break;
260 
261             case E_SET_CONTROL_LABEL :
262                     impl_sta_SetControlLabel(rRequest);
263                     break;
264 
265             case E_GET_CONTROL_LABEL :
266                     impl_sta_GetControlLabel(rRequest);
267                     break;
268 
269             case E_ENABLE_CONTROL :
270                     impl_sta_EnableControl(rRequest);
271                     break;
272 
273             // no default: let the compiler detect changes on enum ERequest !
274         }
275     }
276     catch(...)
277     {}
278 }
279 
280 //-------------------------------------------------------------------------------
after()281 void VistaFilePickerImpl::after()
282 {
283     CoUninitialize();
284 }
285 
286 //-------------------------------------------------------------------------------
impl_sta_addFilePickerListener(const RequestRef & rRequest)287 void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef& rRequest)
288 {
289     // SYNCHRONIZED outside !
290     const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
291     if ( ! xListener.is())
292         return;
293 
294     // SYNCHRONIZED->
295     ::osl::ResettableMutexGuard aLock(m_aMutex);
296     TFileDialogEvents iHandler = m_iEventHandler;
297     aLock.clear();
298     // <- SYNCHRONIZED
299 
300     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
301     if (pHandlerImpl)
302         pHandlerImpl->addFilePickerListener(xListener);
303 }
304 
305 //-------------------------------------------------------------------------------
impl_sta_removeFilePickerListener(const RequestRef & rRequest)306 void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef& rRequest)
307 {
308     // SYNCHRONIZED outside !
309     const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
310     if ( ! xListener.is())
311         return;
312 
313     // SYNCHRONIZED->
314     ::osl::ResettableMutexGuard aLock(m_aMutex);
315     TFileDialogEvents iHandler = m_iEventHandler;
316     aLock.clear();
317     // <- SYNCHRONIZED
318 
319     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
320     if (pHandlerImpl)
321         pHandlerImpl->removeFilePickerListener(xListener);
322 }
323 
324 //-------------------------------------------------------------------------------
impl_sta_appendFilter(const RequestRef & rRequest)325 void VistaFilePickerImpl::impl_sta_appendFilter(const RequestRef& rRequest)
326 {
327     const ::rtl::OUString sTitle  = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, ::rtl::OUString());
328     const ::rtl::OUString sFilter = rRequest->getArgumentOrDefault(PROP_FILTER_VALUE, ::rtl::OUString());
329 
330     // SYNCHRONIZED->
331     ::osl::ResettableMutexGuard aLock(m_aMutex);
332 
333     m_lFilters.addFilter(sTitle, sFilter);
334 }
335 
336 //-------------------------------------------------------------------------------
impl_sta_appendFilterGroup(const RequestRef & rRequest)337 void VistaFilePickerImpl::impl_sta_appendFilterGroup(const RequestRef& rRequest)
338 {
339 	const css::uno::Sequence< css::beans::StringPair > aFilterGroup  =
340 		rRequest->getArgumentOrDefault(PROP_FILTER_GROUP, css::uno::Sequence< css::beans::StringPair >());
341 
342     // SYNCHRONIZED->
343 	::rtl::OUString aEmpty;
344     ::osl::ResettableMutexGuard aLock(m_aMutex);
345 
346     if ( m_lFilters.numFilter() > 0 && aFilterGroup.getLength() > 0 )
347 		m_lFilters.addFilter( STRING_SEPARATOR, aEmpty, sal_True );
348 
349 	::sal_Int32 c = aFilterGroup.getLength();
350     ::sal_Int32 i = 0;
351     for (i=0; i<c; ++i)
352     {
353         const css::beans::StringPair& rFilter = aFilterGroup[i];
354         m_lFilters.addFilter(rFilter.First, rFilter.Second);
355     }
356 }
357 
358 //-------------------------------------------------------------------------------
impl_sta_setCurrentFilter(const RequestRef & rRequest)359 void VistaFilePickerImpl::impl_sta_setCurrentFilter(const RequestRef& rRequest)
360 {
361     const ::rtl::OUString sTitle  = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, ::rtl::OUString());
362 
363     // SYNCHRONIZED->
364     ::osl::ResettableMutexGuard aLock(m_aMutex);
365 
366     m_lFilters.setCurrentFilter(sTitle);
367 }
368 
369 //-------------------------------------------------------------------------------
impl_sta_getCurrentFilter(const RequestRef & rRequest)370 void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef& rRequest)
371 {
372     TFileDialog iDialog = impl_getBaseDialogInterface();
373     UINT        nIndex  = UINT_MAX;
374     HRESULT     hResult = iDialog->GetFileTypeIndex(&nIndex);
375     if (
376         ( FAILED(hResult)    ) ||
377         ( nIndex == UINT_MAX )      // COM dialog sometimes return S_OK for empty filter lists .-(
378        )
379         return;
380 
381     // SYNCHRONIZED->
382     ::osl::ResettableMutexGuard aLock(m_aMutex);
383 
384     ::rtl::OUString sTitle;
385     ::sal_Int32     nRealIndex = (nIndex-1); // COM dialog base on 1 ... filter container on 0 .-)
386     if (
387         (nRealIndex >= 0                         ) &&
388         (m_lFilters.getFilter(nRealIndex, sTitle))
389        )
390         rRequest->setArgument(PROP_FILTER_TITLE, sTitle);
391 	else if ( nRealIndex == -1 ) // Dialog not visible yet
392 	{
393 		sTitle = m_lFilters.getCurrentFilter();
394         rRequest->setArgument(PROP_FILTER_TITLE, sTitle);
395 	}
396 
397     aLock.clear();
398     // <- SYNCHRONIZED
399 }
400 
401 //-------------------------------------------------------------------------------
impl_sta_CreateOpenDialog(const RequestRef & rRequest)402 void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef& rRequest)
403 {
404     // SYNCHRONIZED->
405     ::osl::ResettableMutexGuard aLock(m_aMutex);
406 
407     m_hLastResult = m_iDialogOpen.create();
408     if (FAILED(m_hLastResult))
409         return;
410 
411     TFileDialog iDialog;
412 #ifdef __MINGW32__
413     m_iDialogOpen->QueryInterface(IID_IFileDialog, (void **)(&iDialog));
414 #else
415     m_iDialogOpen.query(&iDialog);
416 #endif
417 
418     TFileDialogEvents iHandler = m_iEventHandler;
419 
420     aLock.clear();
421     // <- SYNCHRONIZED
422 
423 	DWORD nFlags = 0;
424     iDialog->GetOptions ( &nFlags );
425 
426     nFlags &= ~FOS_FORCESHOWHIDDEN;
427     nFlags |=  FOS_PATHMUSTEXIST;
428     nFlags |=  FOS_FILEMUSTEXIST;
429     nFlags |=  FOS_OVERWRITEPROMPT;
430     nFlags |=  FOS_DONTADDTORECENT;
431 
432     iDialog->SetOptions ( nFlags );
433 
434     ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, (::sal_Int32)0);
435 	::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, (::sal_Int32)0);
436     impl_sta_enableFeatures(nFeatures, nTemplate);
437 
438     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
439     if (pHandlerImpl)
440         pHandlerImpl->startListening(iDialog);
441 }
442 
443 //-------------------------------------------------------------------------------
impl_sta_CreateSaveDialog(const RequestRef & rRequest)444 void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef& rRequest)
445 {
446     // SYNCHRONIZED->
447     ::osl::ResettableMutexGuard aLock(m_aMutex);
448 
449     m_hLastResult = m_iDialogSave.create();
450     if (FAILED(m_hLastResult))
451         return;
452 
453     TFileDialogEvents  iHandler = m_iEventHandler;
454     TFileDialog        iDialog;
455 #ifdef __MINGW32__
456     m_iDialogSave->QueryInterface(IID_IFileDialog, (void **)(&iDialog));
457 #else
458     m_iDialogSave.query(&iDialog);
459 #endif
460 
461     aLock.clear();
462     // <- SYNCHRONIZED
463 
464 	DWORD nFlags = 0;
465     iDialog->GetOptions ( &nFlags );
466 
467     nFlags &= ~FOS_FORCESHOWHIDDEN;
468     nFlags |=  FOS_PATHMUSTEXIST;
469     nFlags |=  FOS_FILEMUSTEXIST;
470     nFlags |=  FOS_OVERWRITEPROMPT;
471     nFlags |=  FOS_DONTADDTORECENT;
472 
473     iDialog->SetOptions ( nFlags );
474 
475     ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, (::sal_Int32)0);
476 	::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, (::sal_Int32)0);
477     impl_sta_enableFeatures(nFeatures, nTemplate);
478 
479     VistaFilePickerEventHandler* pHandlerImpl = (VistaFilePickerEventHandler*)iHandler.get();
480     if (pHandlerImpl)
481         pHandlerImpl->startListening(iDialog);
482 }
483 
484 //-------------------------------------------------------------------------------
485 static const ::sal_Int32 GROUP_VERSION         =   1;
486 static const ::sal_Int32 GROUP_TEMPLATE        =   2;
487 static const ::sal_Int32 GROUP_IMAGETEMPLATE   =   3;
488 static const ::sal_Int32 GROUP_CHECKBOXES      =   4;
489 
490 //-------------------------------------------------------------------------------
setLabelToControl(CResourceProvider & rResourceProvider,TFileDialogCustomize iCustom,sal_uInt16 nControlId)491 static void setLabelToControl(CResourceProvider& rResourceProvider, TFileDialogCustomize iCustom, sal_uInt16 nControlId)
492 {
493     ::rtl::OUString aLabel = rResourceProvider.getResString(nControlId);
494     aLabel = SOfficeToWindowsLabel(aLabel);
495     iCustom->SetControlLabel(nControlId, reinterpret_cast<LPCWSTR>(aLabel.getStr()) );
496 }
497 
498 //-------------------------------------------------------------------------------
impl_sta_enableFeatures(::sal_Int32 nFeatures,::sal_Int32 nTemplate)499 void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate)
500 {
501 	GUID aGUID = {};
502 	switch (nTemplate)
503 	{
504         case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE :
505         case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE :
506 			aGUID = CLIENTID_FILEDIALOG_SIMPLE;
507 			break;
508 
509 		case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION :
510         case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS :
511 			aGUID = CLIENTID_FILEDIALOG_OPTIONS;
512 			break;
513 
514 		case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION :
515 			aGUID = CLIENTID_FILESAVE;
516 			break;
517 
518 		case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD :
519 			aGUID = CLIENTID_FILESAVE_PASSWORD;
520 			break;
521 
522         case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION :
523 			aGUID = CLIENTID_FILESAVE_SELECTION;
524 			break;
525 
526         case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE :
527 			aGUID = CLIENTID_FILESAVE_TEMPLATE;
528 			break;
529 
530         case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE :
531 			aGUID = CLIENTID_FILEOPEN_LINK_TEMPLATE;
532 			break;
533 
534         case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY :
535 			aGUID = CLIENTID_FILEOPEN_PLAY;
536 			break;
537 
538         case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW :
539 			aGUID = CLIENTID_FILEOPEN_LINK;
540 			break;
541     }
542 	TFileDialog iDialog = impl_getBaseDialogInterface();
543 	iDialog->SetClientGuid ( aGUID );
544 
545     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
546 
547     if ((nFeatures & FEATURE_VERSION) == FEATURE_VERSION)
548     {
549         iCustom->StartVisualGroup (GROUP_VERSION, L"Version");
550         iCustom->AddComboBox      (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION);
551         iCustom->EndVisualGroup   ();
552         iCustom->MakeProminent    (GROUP_VERSION);
553     }
554 
555     if ((nFeatures & FEATURE_TEMPLATE) == FEATURE_TEMPLATE)
556     {
557         iCustom->StartVisualGroup (GROUP_TEMPLATE, L"Template");
558         iCustom->AddComboBox      (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE);
559         iCustom->EndVisualGroup   ();
560         iCustom->MakeProminent    (GROUP_TEMPLATE);
561     }
562 
563     if ((nFeatures & FEATURE_IMAGETEMPLATE) == FEATURE_IMAGETEMPLATE)
564     {
565         iCustom->StartVisualGroup (GROUP_IMAGETEMPLATE, L"Style");
566         iCustom->AddComboBox      (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE);
567         iCustom->EndVisualGroup   ();
568         iCustom->MakeProminent    (GROUP_IMAGETEMPLATE);
569     }
570 
571 	iCustom->StartVisualGroup (GROUP_CHECKBOXES, L"");
572 
573     sal_uInt16 nControlId(0);
574     if ((nFeatures & FEATURE_AUTOEXTENSION) == FEATURE_AUTOEXTENSION)
575     {
576         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION;
577         iCustom->AddCheckButton (nControlId, L"Auto Extension", true);
578         setLabelToControl(m_ResProvider, iCustom, nControlId);
579     }
580 
581     if ((nFeatures & FEATURE_PASSWORD) == FEATURE_PASSWORD)
582     {
583         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD;
584         iCustom->AddCheckButton (nControlId, L"Password", false);
585         setLabelToControl(m_ResProvider, iCustom, nControlId);
586     }
587 
588     if ((nFeatures & FEATURE_READONLY) == FEATURE_READONLY)
589     {
590         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY;
591         iCustom->AddCheckButton (nControlId, L"Readonly", false);
592         setLabelToControl(m_ResProvider, iCustom, nControlId);
593     }
594 
595     if ((nFeatures & FEATURE_FILTEROPTIONS) == FEATURE_FILTEROPTIONS)
596     {
597         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS;
598         iCustom->AddCheckButton (nControlId, L"Filter Options", false);
599         setLabelToControl(m_ResProvider, iCustom, nControlId);
600     }
601 
602     if ((nFeatures & FEATURE_LINK) == FEATURE_LINK)
603     {
604         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK;
605         iCustom->AddCheckButton (nControlId, L"Link", false);
606         setLabelToControl(m_ResProvider, iCustom, nControlId);
607     }
608 
609     if ((nFeatures & FEATURE_SELECTION) == FEATURE_SELECTION)
610     {
611         nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION;
612         iCustom->AddCheckButton (nControlId, L"Selection", false);
613         setLabelToControl(m_ResProvider, iCustom, nControlId);
614     }
615 
616     /* can be ignored ... new COM dialog supports preview native now  !
617     if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW)
618         iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false);
619     */
620 
621 	iCustom->EndVisualGroup();
622 
623     if ((nFeatures & FEATURE_PLAY) == FEATURE_PLAY)
624         iCustom->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY, L"Play");
625 
626 }
627 
628 //-------------------------------------------------------------------------------
impl_sta_SetMultiSelectionMode(const RequestRef & rRequest)629 void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef& rRequest)
630 {
631     const ::sal_Bool bMultiSelection = rRequest->getArgumentOrDefault(PROP_MULTISELECTION_MODE, (::sal_Bool)sal_True);
632 
633     // SYNCHRONIZED->
634     ::osl::ResettableMutexGuard aLock(m_aMutex);
635     TFileDialog iDialog = impl_getBaseDialogInterface();
636     aLock.clear();
637     // <- SYNCHRONIZED
638 
639 	DWORD nFlags = 0;
640     m_hLastResult = iDialog->GetOptions ( &nFlags );
641 
642     if (bMultiSelection)
643         nFlags |=  FOS_ALLOWMULTISELECT;
644     else
645         nFlags &= ~FOS_ALLOWMULTISELECT;
646 
647     iDialog->SetOptions ( nFlags );
648 }
649 
650 //-------------------------------------------------------------------------------
impl_sta_SetTitle(const RequestRef & rRequest)651 void VistaFilePickerImpl::impl_sta_SetTitle(const RequestRef& rRequest)
652 {
653     ::rtl::OUString sTitle = rRequest->getArgumentOrDefault(PROP_TITLE, ::rtl::OUString());
654 
655     // SYNCHRONIZED->
656     ::osl::ResettableMutexGuard aLock(m_aMutex);
657     TFileDialog iDialog = impl_getBaseDialogInterface();
658     aLock.clear();
659     // <- SYNCHRONIZED
660 
661     iDialog->SetTitle(reinterpret_cast<LPCTSTR>(sTitle.getStr()));
662 }
663 
664 //-------------------------------------------------------------------------------
impl_sta_SetFileName(const RequestRef & rRequest)665 void VistaFilePickerImpl::impl_sta_SetFileName(const RequestRef& rRequest)
666 {
667     ::rtl::OUString sFileName = rRequest->getArgumentOrDefault(PROP_FILENAME, ::rtl::OUString());
668 
669     // SYNCHRONIZED->
670     ::osl::ResettableMutexGuard aLock(m_aMutex);
671     TFileDialog iDialog = impl_getBaseDialogInterface();
672     aLock.clear();
673     // <- SYNCHRONIZED
674 
675     iDialog->SetFileName(reinterpret_cast<LPCTSTR>(sFileName.getStr()));
676 }
677 
678 //-------------------------------------------------------------------------------
impl_sta_SetDirectory(const RequestRef & rRequest)679 void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef& rRequest)
680 {
681     ::rtl::OUString sDirectory = rRequest->getArgumentOrDefault(PROP_DIRECTORY, ::rtl::OUString());
682     bool            bForce     = rRequest->getArgumentOrDefault(PROP_FORCE, false);
683 
684 	if( !m_bInExecute)
685 	{
686 		// Vista stores last used folders for file dialogs
687 		// so we don't want the application to change the folder
688 		// in most cases.
689 		// Store the requested folder in the mean time and decide later
690 		// what to do
691 		m_sDirectory = sDirectory;
692 	}
693 
694     // SYNCHRONIZED->
695     ::osl::ResettableMutexGuard aLock(m_aMutex);
696     TFileDialog iDialog = impl_getBaseDialogInterface();
697     aLock.clear();
698     // <- SYNCHRONIZED
699 
700     ComPtr< IShellItem > pFolder;
701 #ifdef __MINGW32__
702     HRESULT hResult = SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR>(sDirectory.getStr()), NULL, IID_IShellItem, reinterpret_cast<void**>(&pFolder) );
703 #else
704     HRESULT hResult = SHCreateItemFromParsingName( sDirectory.getStr(), NULL, IID_PPV_ARGS(&pFolder) );
705 #endif
706     if ( FAILED(hResult) )
707         return;
708 
709     if ( m_bInExecute || bForce )
710         iDialog->SetFolder(pFolder);
711     else
712     {
713         // Use set default folder as Microsoft recommends in the IFileDialog documentation.
714         iDialog->SetDefaultFolder(pFolder);
715     }
716 }
717 
impl_sta_GetDirectory(const RequestRef & rRequest)718 void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef& rRequest)
719 {
720     TFileDialog iDialog = impl_getBaseDialogInterface();
721     ComPtr< IShellItem > pFolder;
722 	HRESULT hResult = iDialog->GetFolder( &pFolder );
723 	if ( FAILED(hResult) )
724         return;
725 	::rtl::OUString sFolder = lcl_getURLFromShellItem ( pFolder );
726 	if( sFolder.getLength())
727 		rRequest->setArgument( PROP_DIRECTORY, sFolder );
728 }
729 
730 //-------------------------------------------------------------------------------
impl_sta_SetDefaultName(const RequestRef & rRequest)731 void VistaFilePickerImpl::impl_sta_SetDefaultName(const RequestRef& rRequest)
732 {
733 	::rtl::OUString sFilename = rRequest->getArgumentOrDefault(PROP_FILENAME, ::rtl::OUString());
734 	TFileDialog iDialog = impl_getBaseDialogInterface();
735 
736     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
737     if ( ! iCustom.is())
738         return;
739 
740     // if we have the autoextension check box set, remove (or change ???) the extension of the filename
741     // so that the autoextension mechanism can do its job
742     BOOL bValue = FALSE;
743     HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
744     if ( bValue )
745     {
746         sal_Int32 nSepPos = sFilename.lastIndexOf( '.' );
747         if ( -1 != nSepPos )
748             sFilename = sFilename.copy(0, nSepPos);
749     }
750 
751 	iDialog->SetFileName ( reinterpret_cast<LPCTSTR>(sFilename.getStr()));
752 	m_sFilename = sFilename;
753 }
754 
755 //-------------------------------------------------------------------------------
impl_sta_setFiltersOnDialog()756 void VistaFilePickerImpl::impl_sta_setFiltersOnDialog()
757 {
758     // SYNCHRONIZED->
759     ::osl::ResettableMutexGuard aLock(m_aMutex);
760 
761     ::std::vector< COMDLG_FILTERSPEC > lFilters       = lcl_buildFilterList(m_lFilters);
762     ::rtl::OUString                    sCurrentFilter = m_lFilters.getCurrentFilter();
763     sal_Int32                          nCurrentFilter = m_lFilters.getFilterPos(sCurrentFilter);
764     TFileDialog                        iDialog        = impl_getBaseDialogInterface();
765 	TFileDialogCustomize               iCustomize     = impl_getCustomizeInterface();
766 
767     aLock.clear();
768     // <- SYNCHRONIZED
769 
770     if (lFilters.empty())
771         return;
772 
773 	COMDLG_FILTERSPEC	*pFilt = &lFilters[0];
774     iDialog->SetFileTypes(lFilters.size(), pFilt/*&lFilters[0]*/);
775     iDialog->SetFileTypeIndex(nCurrentFilter + 1);
776 
777 	BOOL bValue = FALSE;
778 	HRESULT hResult = iCustomize->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
779 
780 	if ( bValue )
781 	{
782 		LPCWSTR lpFilterExt = lFilters[0].pszSpec;
783 
784 		lpFilterExt = wcsrchr( lpFilterExt, '.' );
785 		if ( lpFilterExt )
786 			lpFilterExt++;
787 		iDialog->SetDefaultExtension( lpFilterExt );
788 	}
789 
790 }
791 
792 //-------------------------------------------------------------------------------
impl_sta_getSelectedFiles(const RequestRef & rRequest)793 void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef& rRequest)
794 {
795     // SYNCHRONIZED->
796     ::osl::ResettableMutexGuard aLock(m_aMutex);
797 
798     TFileOpenDialog iOpen      = m_iDialogOpen;
799     TFileSaveDialog iSave      = m_iDialogSave;
800     ::sal_Bool      bInExecute = m_bInExecute;
801 
802     aLock.clear();
803     // <- SYNCHRONIZED
804 
805     // ask dialog for results
806     // Note        : we must differ between single/multi selection !
807     // Note further: we must react different if dialog is in execute or not .-(
808     ComPtr< IShellItem >      iItem;
809     ComPtr< IShellItemArray > iItems;
810     HRESULT                   hResult = E_FAIL;
811 
812     if (iOpen.is())
813     {
814         if (bInExecute)
815             hResult = iOpen->GetSelectedItems(&iItems);
816         else
817         {
818             hResult = iOpen->GetResults(&iItems);
819             if (FAILED(hResult))
820                 hResult = iOpen->GetResult(&iItem);
821         }
822     }
823     else
824     if (iSave.is())
825     {
826         if (bInExecute)
827             hResult = iSave->GetCurrentSelection(&iItem);
828         else
829             hResult = iSave->GetResult(&iItem);
830     }
831 
832     if (FAILED(hResult))
833         return;
834 
835     // convert and pack results
836     TStringList lFiles;
837     if (iItem.is())
838     {
839         const ::rtl::OUString sURL = lcl_getURLFromShellItem(iItem);
840         if (sURL.getLength() > 0)
841             lFiles.push_back(sURL);
842     }
843 
844     if (iItems.is())
845     {
846         DWORD nCount;
847         hResult = iItems->GetCount(&nCount);
848         if ( SUCCEEDED(hResult) )
849         {
850             for (DWORD i=0; i<nCount; ++i)
851             {
852                 hResult = iItems->GetItemAt(i, &iItem);
853                 if ( SUCCEEDED(hResult) )
854                 {
855                     const ::rtl::OUString sURL = lcl_getURLFromShellItem(iItem);
856                     if (sURL.getLength() > 0)
857                         lFiles.push_back(sURL);
858                 }
859             }
860         }
861     }
862 
863     rRequest->setArgument(PROP_SELECTED_FILES, lFiles.getAsConstList());
864 }
865 
866 //-------------------------------------------------------------------------------
impl_sta_ShowDialogModal(const RequestRef & rRequest)867 void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest)
868 {
869     impl_sta_setFiltersOnDialog();
870 
871     // SYNCHRONIZED->
872     ::osl::ResettableMutexGuard aLock(m_aMutex);
873 
874     TFileDialog iDialog = impl_getBaseDialogInterface();
875     TFileOpenDialog iOpen = m_iDialogOpen;
876     TFileSaveDialog iSave = m_iDialogSave;
877 
878 	// it's important to know if we are showing the dialog.
879     // Some dialog interface methods cant be called then or some
880     // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles())
881     m_bInExecute = sal_True;
882 
883     m_bWasExecuted = sal_True;
884 
885     aLock.clear();
886     // <- SYNCHRONIZED
887 
888 	// we set the directory only if we have a save dialog and a filename
889 	// for the other cases, the file dialog remembers its last location
890 	// according to its client guid.
891 	if( m_sDirectory.getLength())
892 	{
893 		ComPtr< IShellItem > pFolder;
894 		#ifdef __MINGW32__
895 			HRESULT hResult = SHCreateItemFromParsingName ( reinterpret_cast<LPCTSTR>(m_sDirectory.getStr()), NULL, IID_IShellItem, reinterpret_cast<void**>(&pFolder) );
896 		#else
897 			HRESULT hResult = SHCreateItemFromParsingName( m_sDirectory.getStr(), NULL, IID_PPV_ARGS(&pFolder) );
898 		#endif
899 		if ( SUCCEEDED(hResult) )
900         {
901 		    if (m_sFilename.getLength())
902             {
903                 ::rtl::OUString aFileURL(m_sDirectory);
904                 sal_Int32 nIndex = aFileURL.lastIndexOf('/');
905                 if (nIndex != aFileURL.getLength()-1)
906                     aFileURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("/"));
907                 aFileURL += m_sFilename;
908 
909                 TFileDialogCustomize iCustom = impl_getCustomizeInterface();
910 
911                 BOOL bValue = FALSE;
912                 HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
913                 if ( bValue )
914                 {
915                     ::rtl::OUString aExt;
916                     UINT nFileType;
917                     hResult = iDialog->GetFileTypeIndex(&nFileType);
918                     if ( SUCCEEDED(hResult) && nFileType > 0 )
919                     {
920                         ::sal_Int32 nRealIndex = (nFileType-1); // COM dialog base on 1 ... filter container on 0 .-)
921                         ::std::vector< COMDLG_FILTERSPEC > lFilters = lcl_buildFilterList(m_lFilters);
922                         if ( nRealIndex < lFilters.size() )
923                         {
924                             LPCWSTR lpFilterExt = lFilters[nRealIndex].pszSpec;
925 
926                             lpFilterExt = wcsrchr( lpFilterExt, '.' );
927                             if ( lpFilterExt )
928                                 aFileURL += reinterpret_cast<const sal_Unicode*>(lpFilterExt);
929                         }
930                     }
931                 }
932 
933                 // Check existence of file. Set folder only for this special case
934                 ::rtl::OUString aSystemPath;
935                 osl_getSystemPathFromFileURL( aFileURL.pData, &aSystemPath.pData );
936 
937 			    WIN32_FIND_DATA	aFindFileData;
938                 HANDLE	hFind = FindFirstFile( reinterpret_cast<LPCWSTR>(aSystemPath.getStr()), &aFindFileData );
939                 if (hFind != INVALID_HANDLE_VALUE)
940                     iDialog->SetFolder(pFolder);
941                 else
942                     hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
943 
944                 FindClose( hFind );
945             }
946 			else
947 				hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
948 		}
949 	}
950 
951 
952     HRESULT hResult = E_FAIL;
953     try
954     {
955         // show dialog and wait for user decision
956         if (iOpen.is())
957             hResult = iOpen->Show( m_hParentWindow ); // parent window needed
958         else
959         if (iSave.is())
960             hResult = iSave->Show( m_hParentWindow ); // parent window needed
961     }
962     catch(...)
963     {}
964 
965     // SYNCHRONIZED->
966     aLock.reset();
967     m_bInExecute = sal_False;
968     aLock.clear();
969     // <- SYNCHRONIZED
970 
971     if ( FAILED(hResult) )
972         return;
973 
974     impl_sta_getSelectedFiles(rRequest);
975     rRequest->setArgument(PROP_DIALOG_SHOW_RESULT, sal_True);
976 }
977 
978 //-------------------------------------------------------------------------------
impl_getBaseDialogInterface()979 TFileDialog VistaFilePickerImpl::impl_getBaseDialogInterface()
980 {
981     TFileDialog iDialog;
982 
983     // SYNCHRONIZED->
984     ::osl::ResettableMutexGuard aLock(m_aMutex);
985 
986     if (m_iDialogOpen.is())
987 #ifdef __MINGW32__
988         m_iDialogOpen->QueryInterface(IID_IFileDialog, (void**)(&iDialog));
989 #else
990         m_iDialogOpen.query(&iDialog);
991 #endif
992     if (m_iDialogSave.is())
993 #ifdef __MINGW32__
994         m_iDialogSave->QueryInterface(IID_IFileDialog, (void**)(&iDialog));
995 #else
996         m_iDialogSave.query(&iDialog);
997 #endif
998 
999     return iDialog;
1000 }
1001 
1002 //-------------------------------------------------------------------------------
impl_getCustomizeInterface()1003 TFileDialogCustomize VistaFilePickerImpl::impl_getCustomizeInterface()
1004 {
1005     TFileDialogCustomize iCustom;
1006 
1007     // SYNCHRONIZED->
1008     ::osl::ResettableMutexGuard aLock(m_aMutex);
1009 
1010     if (m_iDialogOpen.is())
1011 #ifdef __MINGW32__
1012         m_iDialogOpen->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom));
1013 #else
1014         m_iDialogOpen.query(&iCustom);
1015 #endif
1016     else
1017     if (m_iDialogSave.is())
1018 #ifdef __MINGW32__
1019         m_iDialogSave->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom));
1020 #else
1021         m_iDialogSave.query(&iCustom);
1022 #endif
1023 
1024     return iCustom;
1025 }
1026 
1027 //-------------------------------------------------------------------------------
lcl_removeControlItemsWorkaround(const TFileDialogCustomize & iCustom,::sal_Int16 nControlId)1028 void lcl_removeControlItemsWorkaround(const TFileDialogCustomize& iCustom   ,
1029                                             ::sal_Int16           nControlId)
1030 {
1031     ::sal_Int32 i       = 0;
1032     HRESULT   hResult;
1033 
1034     hResult = iCustom->SetSelectedControlItem(nControlId, 1000);
1035 	hResult = S_OK;
1036     while ( SUCCEEDED(hResult) )
1037         hResult = iCustom->RemoveControlItem(nControlId, i++);
1038 }
1039 
1040 //-------------------------------------------------------------------------------
impl_sta_SetControlValue(const RequestRef & rRequest)1041 void VistaFilePickerImpl::impl_sta_SetControlValue(const RequestRef& rRequest)
1042 {
1043     ::sal_Int16   nId     = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID    );
1044     ::sal_Int16   nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
1045     css::uno::Any aValue  = rRequest->getArgumentOrDefault(PROP_CONTROL_VALUE , css::uno::Any()       );
1046 
1047     // dont check for right values here ...
1048     // most parameters are optional !
1049 
1050     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1051     if ( ! iCustom.is())
1052         return;
1053 
1054     switch (nId)
1055     {
1056         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
1057         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1058         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1059         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1060         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1061         //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1062         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1063             {
1064                 ::sal_Bool bValue   = sal_False;
1065                            aValue >>= bValue;
1066                 iCustom->SetCheckButtonState(nId, bValue);
1067             }
1068             break;
1069 
1070         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION :
1071         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
1072         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
1073             {
1074                 HRESULT hResult;
1075                 switch (nAction)
1076                 {
1077                     case css::ui::dialogs::ControlActions::DELETE_ITEMS :
1078                         {
1079                             hResult = iCustom->RemoveAllControlItems(nId);
1080                             if ( FAILED(hResult) )
1081                                 lcl_removeControlItemsWorkaround(iCustom, nId);
1082                         }
1083                         break;
1084 
1085                     case css::ui::dialogs::ControlActions::ADD_ITEMS :
1086                         {
1087                             css::uno::Sequence< ::rtl::OUString > lItems;
1088                                                        aValue >>= lItems;
1089                             for (::sal_Int32 i=0; i<lItems.getLength(); ++i)
1090                             {
1091                                 const ::rtl::OUString& sItem = lItems[i];
1092                                 hResult = iCustom->AddControlItem(nId, i, reinterpret_cast<LPCTSTR>(sItem.getStr()));
1093                             }
1094                         }
1095                         break;
1096 
1097                     case css::ui::dialogs::ControlActions::SET_SELECT_ITEM :
1098                         {
1099                             ::sal_Int32 nItem    = 0;
1100                                         aValue >>= nItem;
1101                             hResult = iCustom->SetSelectedControlItem(nId, nItem);
1102                         }
1103                         break;
1104                 }
1105             }
1106             break;
1107 
1108         case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
1109             {
1110             }
1111             break;
1112         }
1113 }
1114 
1115 //-------------------------------------------------------------------------------
impl_sta_GetControlValue(const RequestRef & rRequest)1116 void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef& rRequest)
1117 {
1118     ::sal_Int16 nId     = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID    );
1119     ::sal_Int16 nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
1120 
1121     // dont check for right values here ...
1122     // most parameters are optional !
1123 
1124     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1125     if ( ! iCustom.is())
1126         return;
1127 
1128     css::uno::Any aValue;
1129     if( m_bWasExecuted )
1130     switch (nId)
1131     {
1132         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1133         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1134         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1135         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1136         //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1137         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1138             {
1139                 BOOL    bValue  = FALSE;
1140                 HRESULT hResult = iCustom->GetCheckButtonState(nId, &bValue);
1141                 if ( SUCCEEDED(hResult) )
1142                     aValue = css::uno::makeAny((sal_Bool)bValue);
1143             }
1144             break;
1145     }
1146 
1147     if (aValue.hasValue())
1148         rRequest->setArgument(PROP_CONTROL_VALUE, aValue);
1149 }
1150 
1151 //-------------------------------------------------------------------------------
impl_sta_SetControlLabel(const RequestRef & rRequest)1152 void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef& rRequest)
1153 {
1154 	::sal_Int16     nId    = rRequest->getArgumentOrDefault(PROP_CONTROL_ID   , INVALID_CONTROL_ID  );
1155 	::rtl::OUString sLabel = rRequest->getArgumentOrDefault(PROP_CONTROL_LABEL, ::rtl::OUString() );
1156 
1157     // dont check for right values here ...
1158     // most parameters are optional !
1159 
1160     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1161     if ( ! iCustom.is())
1162         return;
1163 	iCustom->SetControlLabel ( nId, reinterpret_cast<LPCTSTR>(sLabel.getStr()));
1164 }
1165 
1166 //-------------------------------------------------------------------------------
impl_sta_GetControlLabel(const RequestRef &)1167 void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef& /*rRequest*/)
1168 {
1169 }
1170 
1171 //-------------------------------------------------------------------------------
impl_sta_EnableControl(const RequestRef & rRequest)1172 void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef& rRequest)
1173 {
1174     ::sal_Int16 nId      = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID  );
1175     ::sal_Bool  bEnabled = rRequest->getArgumentOrDefault(PROP_CONTROL_ENABLE, (::sal_Bool)sal_True);
1176 
1177     // dont check for right values here ...
1178     // most parameters are optional !
1179 
1180     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1181     if ( ! iCustom.is())
1182         return;
1183 
1184     CDCONTROLSTATEF eState = CDCS_VISIBLE;
1185     if (bEnabled)
1186         eState |= CDCS_ENABLED;
1187     else
1188         eState |= CDCS_INACTIVE;
1189 
1190     iCustom->SetControlState(nId, eState);
1191 }
1192 //-------------------------------------------------------------------------------
impl_SetDefaultExtension(const rtl::OUString & currentFilter)1193 void VistaFilePickerImpl::impl_SetDefaultExtension( const rtl::OUString& currentFilter )
1194 {
1195    TFileDialog iDialog = impl_getBaseDialogInterface();
1196    if (currentFilter.getLength())
1197    {
1198 		rtl::OUString FilterExt;
1199 		m_lFilters.getFilter(currentFilter, FilterExt);
1200 
1201 		sal_Int32 posOfPoint = FilterExt.indexOf(L'.');
1202 		const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1;
1203 
1204 		sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1;
1205 		if (posOfSemiColon < 0)
1206 			posOfSemiColon = FilterExt.getLength() - 1;
1207 
1208 		FilterExt = rtl::OUString(pFirstExtStart, posOfSemiColon - posOfPoint);
1209 		iDialog->SetDefaultExtension ( reinterpret_cast<LPCTSTR>(FilterExt.getStr()) );
1210    }
1211 }
1212 
impl_refreshFileDialog(TFileDialog iDialog)1213 static void impl_refreshFileDialog( TFileDialog iDialog )
1214 {
1215 	if ( SUCCEEDED(iDialog->SetFileName(L"")) &&
1216 	     SUCCEEDED(iDialog->SetFileName(L"*.*")) )
1217 	{
1218 		IOleWindow* iOleWindow;
1219 #ifdef __MINGW32__
1220 		if (SUCCEEDED(iDialog->QueryInterface(IID_IOleWindow, reinterpret_cast<void**>(&iOleWindow))))
1221 #else
1222 		if (SUCCEEDED(iDialog->QueryInterface(IID_PPV_ARGS(&iOleWindow))))
1223 #endif
1224 		{
1225 			HWND hwnd;
1226 			if (SUCCEEDED(iOleWindow->GetWindow(&hwnd)))
1227 			{
1228 				PostMessage(hwnd, WM_COMMAND, IDOK, 0);
1229 			}
1230 			iOleWindow->Release();
1231 		}
1232 	}
1233 }
1234 
1235 //-------------------------------------------------------------------------------
onAutoExtensionChanged(bool bChecked)1236 void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked)
1237 {
1238     // SYNCHRONIZED->
1239     ::osl::ResettableMutexGuard aLock(m_aMutex);
1240 
1241 	const ::rtl::OUString sFilter = m_lFilters.getCurrentFilter ();
1242 		  ::rtl::OUString sExt    ;
1243 	if ( !m_lFilters.getFilter (sFilter, sExt))
1244 		return;
1245 
1246     TFileDialog iDialog = impl_getBaseDialogInterface();
1247 
1248     aLock.clear();
1249     // <- SYNCHRONIZED
1250 
1251 	LPCWSTR pExt = 0;
1252 	if ( bChecked )
1253 	{
1254 		pExt = reinterpret_cast<LPCTSTR>(sExt.getStr());
1255 		pExt = wcsrchr( pExt, '.' );
1256 		if ( pExt )
1257 			pExt++;
1258 	}
1259 	iDialog->SetDefaultExtension( pExt );
1260 }
1261 
onFileTypeChanged(UINT)1262 bool VistaFilePickerImpl::onFileTypeChanged( UINT /*nTypeIndex*/ )
1263 {
1264 	return true;
1265 }
1266 
1267 } // namespace vista
1268 } // namespace win32
1269 } // namespace fpicker
1270