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 
44  inline bool is_current_process_window(HWND hwnd)
45 {
46     DWORD pid;
47     GetWindowThreadProcessId(hwnd, &pid);
48     return (pid == GetCurrentProcessId());
49 }
50 
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 //-----------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
157 VistaFilePickerImpl::~VistaFilePickerImpl()
158 {
159 }
160 
161 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
281 void VistaFilePickerImpl::after()
282 {
283     CoUninitialize();
284 }
285 
286 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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, 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 
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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 //-------------------------------------------------------------------------------
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, 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) )
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 		                LPCWSTR lpFilterExt = lFilters[nRealIndex].pszSpec;
923 
924 		                lpFilterExt = wcsrchr( lpFilterExt, '.' );
925 		                if ( lpFilterExt )
926                             aFileURL += reinterpret_cast<const sal_Unicode*>(lpFilterExt);
927                     }
928                 }
929 
930                 // Check existence of file. Set folder only for this special case
931                 ::rtl::OUString aSystemPath;
932                 osl_getSystemPathFromFileURL( aFileURL.pData, &aSystemPath.pData );
933 
934 			    WIN32_FIND_DATA	aFindFileData;
935                 HANDLE	hFind = FindFirstFile( reinterpret_cast<LPCWSTR>(aSystemPath.getStr()), &aFindFileData );
936                 if (hFind != INVALID_HANDLE_VALUE)
937                     iDialog->SetFolder(pFolder);
938                 else
939                     hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
940 
941                 FindClose( hFind );
942             }
943 			else
944 				hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
945 		}
946 	}
947 
948 
949     HRESULT hResult = E_FAIL;
950     try
951     {
952         // show dialog and wait for user decision
953         if (iOpen.is())
954             hResult = iOpen->Show( m_hParentWindow ); // parent window needed
955         else
956         if (iSave.is())
957             hResult = iSave->Show( m_hParentWindow ); // parent window needed
958     }
959     catch(...)
960     {}
961 
962     // SYNCHRONIZED->
963     aLock.reset();
964     m_bInExecute = sal_False;
965     aLock.clear();
966     // <- SYNCHRONIZED
967 
968     if ( FAILED(hResult) )
969         return;
970 
971     impl_sta_getSelectedFiles(rRequest);
972     rRequest->setArgument(PROP_DIALOG_SHOW_RESULT, sal_True);
973 }
974 
975 //-------------------------------------------------------------------------------
976 TFileDialog VistaFilePickerImpl::impl_getBaseDialogInterface()
977 {
978     TFileDialog iDialog;
979 
980     // SYNCHRONIZED->
981     ::osl::ResettableMutexGuard aLock(m_aMutex);
982 
983     if (m_iDialogOpen.is())
984 #ifdef __MINGW32__
985         m_iDialogOpen->QueryInterface(IID_IFileDialog, (void**)(&iDialog));
986 #else
987         m_iDialogOpen.query(&iDialog);
988 #endif
989     if (m_iDialogSave.is())
990 #ifdef __MINGW32__
991         m_iDialogSave->QueryInterface(IID_IFileDialog, (void**)(&iDialog));
992 #else
993         m_iDialogSave.query(&iDialog);
994 #endif
995 
996     return iDialog;
997 }
998 
999 //-------------------------------------------------------------------------------
1000 TFileDialogCustomize VistaFilePickerImpl::impl_getCustomizeInterface()
1001 {
1002     TFileDialogCustomize iCustom;
1003 
1004     // SYNCHRONIZED->
1005     ::osl::ResettableMutexGuard aLock(m_aMutex);
1006 
1007     if (m_iDialogOpen.is())
1008 #ifdef __MINGW32__
1009         m_iDialogOpen->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom));
1010 #else
1011         m_iDialogOpen.query(&iCustom);
1012 #endif
1013     else
1014     if (m_iDialogSave.is())
1015 #ifdef __MINGW32__
1016         m_iDialogSave->QueryInterface(IID_IFileDialogCustomize, (void**)(&iCustom));
1017 #else
1018         m_iDialogSave.query(&iCustom);
1019 #endif
1020 
1021     return iCustom;
1022 }
1023 
1024 //-------------------------------------------------------------------------------
1025 void lcl_removeControlItemsWorkaround(const TFileDialogCustomize& iCustom   ,
1026                                             ::sal_Int16           nControlId)
1027 {
1028     ::sal_Int32 i       = 0;
1029     HRESULT   hResult;
1030 
1031     hResult = iCustom->SetSelectedControlItem(nControlId, 1000);
1032 	hResult = S_OK;
1033     while ( SUCCEEDED(hResult) )
1034         hResult = iCustom->RemoveControlItem(nControlId, i++);
1035 }
1036 
1037 //-------------------------------------------------------------------------------
1038 void VistaFilePickerImpl::impl_sta_SetControlValue(const RequestRef& rRequest)
1039 {
1040     ::sal_Int16   nId     = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID    );
1041     ::sal_Int16   nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
1042     css::uno::Any aValue  = rRequest->getArgumentOrDefault(PROP_CONTROL_VALUE , css::uno::Any()       );
1043 
1044     // dont check for right values here ...
1045     // most parameters are optional !
1046 
1047     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1048     if ( ! iCustom.is())
1049         return;
1050 
1051     switch (nId)
1052     {
1053         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
1054         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1055         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1056         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1057         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1058         //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1059         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1060             {
1061                 ::sal_Bool bValue   = sal_False;
1062                            aValue >>= bValue;
1063                 iCustom->SetCheckButtonState(nId, bValue);
1064             }
1065             break;
1066 
1067         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION :
1068         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
1069         case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
1070             {
1071                 HRESULT hResult;
1072                 switch (nAction)
1073                 {
1074                     case css::ui::dialogs::ControlActions::DELETE_ITEMS :
1075                         {
1076                             hResult = iCustom->RemoveAllControlItems(nId);
1077                             if ( FAILED(hResult) )
1078                                 lcl_removeControlItemsWorkaround(iCustom, nId);
1079                         }
1080                         break;
1081 
1082                     case css::ui::dialogs::ControlActions::ADD_ITEMS :
1083                         {
1084                             css::uno::Sequence< ::rtl::OUString > lItems;
1085                                                        aValue >>= lItems;
1086                             for (::sal_Int32 i=0; i<lItems.getLength(); ++i)
1087                             {
1088                                 const ::rtl::OUString& sItem = lItems[i];
1089                                 hResult = iCustom->AddControlItem(nId, i, reinterpret_cast<LPCTSTR>(sItem.getStr()));
1090                             }
1091                         }
1092                         break;
1093 
1094                     case css::ui::dialogs::ControlActions::SET_SELECT_ITEM :
1095                         {
1096                             ::sal_Int32 nItem    = 0;
1097                                         aValue >>= nItem;
1098                             hResult = iCustom->SetSelectedControlItem(nId, nItem);
1099                         }
1100                         break;
1101                 }
1102             }
1103             break;
1104 
1105         case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
1106             {
1107             }
1108             break;
1109         }
1110 }
1111 
1112 //-------------------------------------------------------------------------------
1113 void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef& rRequest)
1114 {
1115     ::sal_Int16 nId     = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID    );
1116     ::sal_Int16 nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
1117 
1118     // dont check for right values here ...
1119     // most parameters are optional !
1120 
1121     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1122     if ( ! iCustom.is())
1123         return;
1124 
1125     css::uno::Any aValue;
1126     if( m_bWasExecuted )
1127     switch (nId)
1128     {
1129         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
1130         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
1131         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
1132         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
1133         //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
1134         case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
1135             {
1136                 BOOL    bValue  = FALSE;
1137                 HRESULT hResult = iCustom->GetCheckButtonState(nId, &bValue);
1138                 if ( SUCCEEDED(hResult) )
1139                     aValue = css::uno::makeAny((sal_Bool)bValue);
1140             }
1141             break;
1142     }
1143 
1144     if (aValue.hasValue())
1145         rRequest->setArgument(PROP_CONTROL_VALUE, aValue);
1146 }
1147 
1148 //-------------------------------------------------------------------------------
1149 void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef& rRequest)
1150 {
1151 	::sal_Int16     nId    = rRequest->getArgumentOrDefault(PROP_CONTROL_ID   , INVALID_CONTROL_ID  );
1152 	::rtl::OUString sLabel = rRequest->getArgumentOrDefault(PROP_CONTROL_LABEL, ::rtl::OUString() );
1153 
1154     // dont check for right values here ...
1155     // most parameters are optional !
1156 
1157     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1158     if ( ! iCustom.is())
1159         return;
1160 	iCustom->SetControlLabel ( nId, reinterpret_cast<LPCTSTR>(sLabel.getStr()));
1161 }
1162 
1163 //-------------------------------------------------------------------------------
1164 void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef& /*rRequest*/)
1165 {
1166 }
1167 
1168 //-------------------------------------------------------------------------------
1169 void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef& rRequest)
1170 {
1171     ::sal_Int16 nId      = rRequest->getArgumentOrDefault(PROP_CONTROL_ID    , INVALID_CONTROL_ID  );
1172     ::sal_Bool  bEnabled = rRequest->getArgumentOrDefault(PROP_CONTROL_ENABLE, (::sal_Bool)sal_True);
1173 
1174     // dont check for right values here ...
1175     // most parameters are optional !
1176 
1177     TFileDialogCustomize iCustom = impl_getCustomizeInterface();
1178     if ( ! iCustom.is())
1179         return;
1180 
1181     CDCONTROLSTATEF eState = CDCS_VISIBLE;
1182     if (bEnabled)
1183         eState |= CDCS_ENABLED;
1184     else
1185         eState |= CDCS_INACTIVE;
1186 
1187     iCustom->SetControlState(nId, eState);
1188 }
1189 //-------------------------------------------------------------------------------
1190 void VistaFilePickerImpl::impl_SetDefaultExtension( const rtl::OUString& currentFilter )
1191 {
1192    TFileDialog iDialog = impl_getBaseDialogInterface();
1193    if (currentFilter.getLength())
1194    {
1195 		rtl::OUString FilterExt;
1196 		m_lFilters.getFilter(currentFilter, FilterExt);
1197 
1198 		sal_Int32 posOfPoint = FilterExt.indexOf(L'.');
1199 		const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1;
1200 
1201 		sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1;
1202 		if (posOfSemiColon < 0)
1203 			posOfSemiColon = FilterExt.getLength() - 1;
1204 
1205 		FilterExt = rtl::OUString(pFirstExtStart, posOfSemiColon - posOfPoint);
1206 		iDialog->SetDefaultExtension ( reinterpret_cast<LPCTSTR>(FilterExt.getStr()) );
1207    }
1208 }
1209 
1210 static void impl_refreshFileDialog( TFileDialog iDialog )
1211 {
1212 	if ( SUCCEEDED(iDialog->SetFileName(L"")) &&
1213 	     SUCCEEDED(iDialog->SetFileName(L"*.*")) )
1214 	{
1215 		IOleWindow* iOleWindow;
1216 #ifdef __MINGW32__
1217 		if (SUCCEEDED(iDialog->QueryInterface(IID_IOleWindow, reinterpret_cast<void**>(&iOleWindow))))
1218 #else
1219 		if (SUCCEEDED(iDialog->QueryInterface(IID_PPV_ARGS(&iOleWindow))))
1220 #endif
1221 		{
1222 			HWND hwnd;
1223 			if (SUCCEEDED(iOleWindow->GetWindow(&hwnd)))
1224 			{
1225 				PostMessage(hwnd, WM_COMMAND, IDOK, 0);
1226 			}
1227 			iOleWindow->Release();
1228 		}
1229 	}
1230 }
1231 
1232 //-------------------------------------------------------------------------------
1233 void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked)
1234 {
1235     // SYNCHRONIZED->
1236     ::osl::ResettableMutexGuard aLock(m_aMutex);
1237 
1238 	const ::rtl::OUString sFilter = m_lFilters.getCurrentFilter ();
1239 		  ::rtl::OUString sExt    ;
1240 	if ( !m_lFilters.getFilter (sFilter, sExt))
1241 		return;
1242 
1243     TFileDialog iDialog = impl_getBaseDialogInterface();
1244 
1245     aLock.clear();
1246     // <- SYNCHRONIZED
1247 
1248 	LPCWSTR pExt = 0;
1249 	if ( bChecked )
1250 	{
1251 		pExt = reinterpret_cast<LPCTSTR>(sExt.getStr());
1252 		pExt = wcsrchr( pExt, '.' );
1253 		if ( pExt )
1254 			pExt++;
1255 	}
1256 	iDialog->SetDefaultExtension( pExt );
1257 }
1258 
1259 bool VistaFilePickerImpl::onFileTypeChanged( UINT /*nTypeIndex*/ )
1260 {
1261 	return true;
1262 }
1263 
1264 } // namespace vista
1265 } // namespace win32
1266 } // namespace fpicker
1267