1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_fpicker.hxx"
30 
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
34 
35 #include "shared.hxx"
36 #include "WinFileOpenImpl.hxx"
37 #include <osl/diagnose.h>
38 #include <osl/file.hxx>
39 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
40 #include <com/sun/star/ui/dialogs/FilePickerEvent.hpp>
41 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
42 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
43 #include <com/sun/star/ui/dialogs/FilePreviewImageFormats.hpp>
44 #include <com/sun/star/ui/dialogs/ListBoxControlActions.hpp>
45 #include "..\misc\WinImplHelper.hxx"
46 
47 #ifndef _FILEPICKER_HXX_
48 #include "filepicker.hxx"
49 #endif
50 #include "controlaccess.hxx"
51 #include <rtl/ustrbuf.hxx>
52 #include <rtl/string.hxx>
53 #include <osl/thread.hxx>
54 #include "filepickerstate.hxx"
55 
56 //------------------------------------------------------------------------
57 // namespace directives
58 //------------------------------------------------------------------------
59 
60 using namespace com::sun::star;
61 
62 using com::sun::star::ui::dialogs::FilePickerEvent;
63 using com::sun::star::lang::IllegalArgumentException;
64 using com::sun::star::ui::dialogs::XFilePicker2;
65 
66 using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
67 using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
68 using namespace ::com::sun::star::ui::dialogs::ListboxControlActions;
69 
70 //-------------------------------------------------------------------------
71 // to distinguish what to do in the enum child window callback function
72 //-------------------------------------------------------------------------
73 
74 enum ECW_ACTION_T
75 {
76     INIT_CUSTOM_CONTROLS,
77     CACHE_CONTROL_VALUES
78 };
79 
80 struct EnumParam
81 {
82     ECW_ACTION_T        m_action;
83     CWinFileOpenImpl*   m_instance;
84 
85     EnumParam( ECW_ACTION_T action, CWinFileOpenImpl* instance ):
86         m_action( action ),
87         m_instance( instance )
88     {}
89 };
90 
91 //-------------------------------------------------------------------------
92 // ctor
93 //-------------------------------------------------------------------------
94 
95 CWinFileOpenImpl::CWinFileOpenImpl(
96 	CFilePicker* aFilePicker,
97 	sal_Bool bFileOpenDialog,
98 	sal_uInt32 dwFlags,
99 	sal_uInt32 dwTemplateId,
100 	HINSTANCE hInstance) :
101 	CFileOpenDialog(bFileOpenDialog, dwFlags, dwTemplateId, hInstance),
102 	m_filterContainer(new CFilterContainer()),
103 	m_Preview(new CPreviewAdapter(hInstance)),
104 	m_CustomControlFactory(new CCustomControlFactory()),
105 	m_CustomControls(m_CustomControlFactory->CreateCustomControlContainer()),
106 	m_FilePicker(aFilePicker),
107     m_bInitialSelChanged(sal_True),
108     m_HelpPopupWindow(hInstance, m_hwndFileOpenDlg),
109     m_ExecuteFilePickerState(new CExecuteFilePickerState()),
110     m_NonExecuteFilePickerState(new CNonExecuteFilePickerState())
111 {
112     m_FilePickerState = m_NonExecuteFilePickerState;
113 }
114 
115 //------------------------------------------------------------------------
116 // dtor
117 //------------------------------------------------------------------------
118 
119 CWinFileOpenImpl::~CWinFileOpenImpl()
120 {
121     delete m_ExecuteFilePickerState;
122     delete m_NonExecuteFilePickerState;
123 }
124 
125 //------------------------------------------------------------------------
126 // we expect the directory in URL format
127 //------------------------------------------------------------------------
128 
129 void CWinFileOpenImpl::setDisplayDirectory(const rtl::OUString& aDirectory)
130 	throw( IllegalArgumentException, uno::RuntimeException )
131 {
132     rtl::OUString aSysDirectory;
133 	if( aDirectory.getLength() > 0)
134 	{
135         if ( ::osl::FileBase::E_None !=
136              ::osl::FileBase::getSystemPathFromFileURL(aDirectory,aSysDirectory))
137             throw IllegalArgumentException(
138 				rtl::OUString::createFromAscii("Invalid directory"),
139 				static_cast<XFilePicker2*>(m_FilePicker), 1);
140 
141         // we ensure that there is a trailing '/' at the end of
142         // he given file url, because the windows functions only
143         // works correctly when providing "c:\" or an environment
144         // variable like "=c:=c:\.." etc. is set, else the
145         // FolderPicker would stand in the root of the shell
146         // hierarchie which is the desktop folder
147         if ( aSysDirectory.lastIndexOf(BACKSLASH) != (aSysDirectory.getLength() - 1))
148             aSysDirectory += BACKSLASH;
149 	}
150 
151 	// call base class method
152 	CFileOpenDialog::setDisplayDirectory(aSysDirectory);
153 }
154 
155 //------------------------------------------------------------------------
156 // we return the directory in URL format
157 //------------------------------------------------------------------------
158 
159 rtl::OUString CWinFileOpenImpl::getDisplayDirectory() throw(uno::RuntimeException)
160 {
161     return m_FilePickerState->getDisplayDirectory(this);
162 }
163 
164 //-----------------------------------------------------------------------------------------
165 //
166 //-----------------------------------------------------------------------------------------
167 
168 void SAL_CALL CWinFileOpenImpl::setDefaultName(const rtl::OUString& aName)
169 	throw( IllegalArgumentException, uno::RuntimeException )
170 {
171     // we don't set the default name directly
172     // because this influences how the file open
173     // dialog sets the initial path when it is about
174     // to open (see MSDN: OPENFILENAME)
175     // so we save the default name which should
176     // appear in the file-name-box and set
177     // this name when processing onInitDone
178     m_defaultName = aName;
179 }
180 
181 //-----------------------------------------------------------------------------------------
182 // return format: URL
183 // if multiselection is allowed there are two different cases
184 // 1. one file selected: the sequence contains one entry path\filename.ext
185 // 2. multiple files selected: the sequence contains multiple entries
186 //    the first entry is the path url, all other entries are file names
187 //-----------------------------------------------------------------------------------------
188 
189 uno::Sequence<rtl::OUString> SAL_CALL CWinFileOpenImpl::getFiles()
190 	throw(uno::RuntimeException)
191 {
192     return m_FilePickerState->getFiles(this);
193 }
194 
195 //-----------------------------------------------------------------------------------------
196 // shows the FileOpen/FileSave dialog
197 //-----------------------------------------------------------------------------------------
198 
199 sal_Int16 SAL_CALL CWinFileOpenImpl::execute(  ) throw(uno::RuntimeException)
200 {
201 	sal_Int16 rc = CFileOpenDialog::doModal();
202 
203 	if (1 == rc)
204         rc = ::com::sun::star::ui::dialogs::ExecutableDialogResults::OK;
205 	else if (0 == rc)
206         rc = ::com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL;
207 	else
208 		throw uno::RuntimeException(
209 			rtl::OUString::createFromAscii("Error executing dialog"),
210 			static_cast<XFilePicker2*>(m_FilePicker));
211 
212 	return rc;
213 }
214 
215 //-----------------------------------------------------------------------------------------
216 // appends a new filter
217 // returns false if the title (aTitle) was already added or the title or the filter are
218 // empty
219 //-----------------------------------------------------------------------------------------
220 
221 void SAL_CALL CWinFileOpenImpl::appendFilter(const rtl::OUString& aTitle, const rtl::OUString& aFilter)
222 	throw(IllegalArgumentException, uno::RuntimeException)
223 {
224 	sal_Bool bRet = m_filterContainer->addFilter(aTitle, aFilter);
225 
226     if (!bRet)
227         throw IllegalArgumentException(
228             rtl::OUString::createFromAscii("filter already exists"),
229             static_cast<XFilePicker2*>(m_FilePicker), 1);
230 
231     // #95345# see MSDN OPENFILENAME
232     // If nFilterIndex is zero and lpstrCustomFilter is NULL,
233     // the system uses the first filter in the lpstrFilter buffer.
234     // to reflect this we must set the filter index so that calls
235     // to getSelectedFilterIndex without explicitly calling
236     // setFilterIndex before does not return 0 which leads to a
237     // false state
238     if (0 == getSelectedFilterIndex())
239         CFileOpenDialog::setFilterIndex(1);
240 }
241 
242 //-----------------------------------------------------------------------------------------
243 // sets a current filter
244 //-----------------------------------------------------------------------------------------
245 
246 void SAL_CALL CWinFileOpenImpl::setCurrentFilter(const rtl::OUString& aTitle)
247 	throw( IllegalArgumentException, uno::RuntimeException)
248 {
249 	sal_Int32 filterPos = m_filterContainer->getFilterPos(aTitle);
250 
251 	if (filterPos < 0)
252 		throw IllegalArgumentException(
253 			rtl::OUString::createFromAscii("filter doesn't exist"),
254 			static_cast<XFilePicker2*>(m_FilePicker), 1);
255 
256 	// filter index of the base class starts with 1
257 	CFileOpenDialog::setFilterIndex(filterPos + 1);
258 }
259 
260 //-----------------------------------------------------------------------------------------
261 // returns the currently selected filter
262 //-----------------------------------------------------------------------------------------
263 
264 rtl::OUString SAL_CALL CWinFileOpenImpl::getCurrentFilter() throw(uno::RuntimeException)
265 {
266 	sal_uInt32 nIndex = getSelectedFilterIndex();
267 
268 	rtl::OUString currentFilter;
269 	if (nIndex > 0)
270 	{
271 		// filter index of the base class starts with 1
272 		if (!m_filterContainer->getFilter(nIndex - 1, currentFilter)) {
273             OSL_ASSERT(false);
274         }
275 	}
276 
277 	return currentFilter;
278 }
279 
280 //-----------------------------------------------------------------------------------------
281 //
282 //-----------------------------------------------------------------------------------------
283 
284 inline void SAL_CALL CWinFileOpenImpl::appendFilterGroupSeparator()
285 {
286     m_filterContainer->addFilter(FILTER_SEPARATOR, ALL_FILES_WILDCARD, ALLOW_DUPLICATES);
287 }
288 
289 //-----------------------------------------------------------------------------------------
290 // XFilterGroupManager
291 //-----------------------------------------------------------------------------------------
292 
293 void SAL_CALL CWinFileOpenImpl::appendFilterGroup(const rtl::OUString& sGroupTitle, const uno::Sequence<beans::StringPair>& aFilters)
294     throw (IllegalArgumentException, uno::RuntimeException)
295 {
296     (void) sGroupTitle; // avoid warning
297     OSL_ENSURE(0 == sGroupTitle.getLength(), "appendFilterGroup: Parameter 'GroupTitle' currently ignored");
298 
299     sal_Int32 nFilters = aFilters.getLength();
300 
301     OSL_PRECOND(nFilters > 0, "Empty filter list");
302 
303     if (nFilters > 0)
304     {
305         // append a separator before the next group if
306         // there is already a group of filters
307         if (m_filterContainer->numFilter() > 0)
308             appendFilterGroupSeparator();
309 
310         for (int i = 0; i < nFilters; i++)
311             appendFilter(aFilters[i].First, aFilters[i].Second);
312     }
313 }
314 
315 //=================================================================================================================
316 // XExtendedFilePicker
317 //=================================================================================================================
318 
319 // #i90917: Due to a different feature set for the system-dependent file pickers
320 // it's possible that generic code (e.g. sfx2) provides control ids
321 // (see ExtendedFilePickerElementIds::LISTBOX_FILTER_SELECTOR) which are NOT
322 // available on all platforms. This filter function should filter out control ids
323 // which are only available on KDE/GTK file pickers.
324 static bool filterControlCommand( sal_Int16 nControlId )
325 {
326 	if ( nControlId == LISTBOX_FILTER_SELECTOR )
327 		return true;
328 	return false;
329 }
330 
331 void SAL_CALL CWinFileOpenImpl::setValue(sal_Int16 aControlId, sal_Int16 aControlAction, const uno::Any& aValue)
332 	throw(uno::RuntimeException)
333 {
334     OSL_ASSERT(m_FilePickerState);
335 	if ( !filterControlCommand( aControlId ))
336 		m_FilePickerState->setValue(aControlId, aControlAction, aValue);
337 }
338 
339 //-----------------------------------------------------------------------------------------
340 // returns the value of an custom template element
341 // we assume that there are only checkboxes or comboboxes
342 //-----------------------------------------------------------------------------------------
343 
344 uno::Any SAL_CALL CWinFileOpenImpl::getValue(sal_Int16 aControlId, sal_Int16 aControlAction)
345 	throw(uno::RuntimeException)
346 {
347     OSL_ASSERT(m_FilePickerState);
348 	if ( !filterControlCommand( aControlId ))
349 		return m_FilePickerState->getValue(aControlId, aControlAction);
350 	else
351 		return uno::Any();
352 }
353 
354 //-----------------------------------------------------------------------------------------
355 // enables a custom template element
356 //-----------------------------------------------------------------------------------------
357 
358 void SAL_CALL CWinFileOpenImpl::enableControl(sal_Int16 ControlID, sal_Bool bEnable)
359 	throw(uno::RuntimeException)
360 {
361     OSL_ASSERT(m_FilePickerState);
362     if ( !filterControlCommand( ControlID ))
363 		m_FilePickerState->enableControl(ControlID, bEnable);
364 }
365 
366 //-----------------------------------------------------------------------------------------
367 //
368 //-----------------------------------------------------------------------------------------
369 
370 void SAL_CALL CWinFileOpenImpl::setLabel( sal_Int16 aControlId, const rtl::OUString& aLabel )
371     throw (uno::RuntimeException)
372 {
373     OSL_ASSERT(m_FilePickerState);
374 	if ( !filterControlCommand( aControlId ))
375 		m_FilePickerState->setLabel(aControlId, aLabel);
376 }
377 
378 //-----------------------------------------------------------------------------------------
379 //
380 //-----------------------------------------------------------------------------------------
381 
382 rtl::OUString SAL_CALL CWinFileOpenImpl::getLabel( sal_Int16 aControlId )
383 		throw (uno::RuntimeException)
384 {
385     OSL_ASSERT(m_FilePickerState);
386 	if ( !filterControlCommand( aControlId ))
387 		return m_FilePickerState->getLabel(aControlId);
388 	else
389 		return rtl::OUString();
390 }
391 
392 //-----------------------------------------------------------------------------------------
393 //
394 //-----------------------------------------------------------------------------------------
395 
396 uno::Sequence<sal_Int16> SAL_CALL CWinFileOpenImpl::getSupportedImageFormats()
397     throw (uno::RuntimeException)
398 {
399     return m_Preview->getSupportedImageFormats();
400 }
401 
402 //-----------------------------------------------------------------------------------------
403 //
404 //-----------------------------------------------------------------------------------------
405 
406 sal_Int32 SAL_CALL CWinFileOpenImpl::getTargetColorDepth()
407     throw (uno::RuntimeException)
408 {
409     return m_Preview->getTargetColorDepth();
410 }
411 
412 //-----------------------------------------------------------------------------------------
413 //
414 //-----------------------------------------------------------------------------------------
415 
416 sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableWidth()
417         throw (uno::RuntimeException)
418 {
419     return m_Preview->getAvailableWidth();
420 }
421 
422 //-----------------------------------------------------------------------------------------
423 //
424 //-----------------------------------------------------------------------------------------
425 
426 sal_Int32 SAL_CALL CWinFileOpenImpl::getAvailableHeight()
427     throw (uno::RuntimeException)
428 {
429     return m_Preview->getAvailableHeight();
430 }
431 
432 //-----------------------------------------------------------------------------------------
433 //
434 //-----------------------------------------------------------------------------------------
435 
436 void SAL_CALL CWinFileOpenImpl::setImage(sal_Int16 aImageFormat, const uno::Any& aImage)
437     throw (IllegalArgumentException, uno::RuntimeException)
438 {
439     m_Preview->setImage(aImageFormat,aImage);
440 }
441 
442 //-----------------------------------------------------------------------------------------
443 //
444 //-----------------------------------------------------------------------------------------
445 
446 sal_Bool SAL_CALL CWinFileOpenImpl::setShowState(sal_Bool bShowState)
447         throw (uno::RuntimeException)
448 {
449     return m_Preview->setShowState(bShowState);
450 }
451 
452 //-----------------------------------------------------------------------------------------
453 //
454 //-----------------------------------------------------------------------------------------
455 
456 sal_Bool SAL_CALL CWinFileOpenImpl::getShowState()
457     throw (uno::RuntimeException)
458 {
459     return m_Preview->getShowState();
460 }
461 
462 //-----------------------------------------------------------------------------------------
463 //
464 //-----------------------------------------------------------------------------------------
465 
466 void SAL_CALL CWinFileOpenImpl::cancel()
467 {
468     if (IsWindow(m_hwndFileOpenDlg))
469     {
470         // simulate a mouse click to the
471         // cancel button
472         PostMessage(
473             m_hwndFileOpenDlg,
474             WM_COMMAND,
475             MAKEWPARAM(IDCANCEL,BN_CLICKED),
476             (LPARAM)GetDlgItem(m_hwndFileOpenDlg, IDCANCEL));
477     }
478 }
479 
480 //-----------------------------------------------------------------------------------------
481 // returns the id of a custom template element
482 //-----------------------------------------------------------------------------------------
483 
484 sal_Int16 SAL_CALL CWinFileOpenImpl::getFocused()
485 {
486 	int nID = GetDlgCtrlID(GetFocus());
487 
488 	// we don't forward id's of standard file open
489     // dialog elements (ctlFirst is defined in dlgs.h
490     // in MS Platform SDK)
491 	if (nID >= ctlFirst)
492 		nID = 0;
493 
494 	return sal::static_int_cast< sal_Int16 >(nID);
495 }
496 
497 //-----------------------------------------------------------------------------------------
498 //
499 //-----------------------------------------------------------------------------------------
500 
501 inline sal_Bool SAL_CALL CWinFileOpenImpl::IsCustomControlHelpRequested(LPHELPINFO lphi) const
502 {
503 	return ((lphi->iCtrlId != IDOK) && (lphi->iCtrlId != IDCANCEL) && (lphi->iCtrlId < ctlFirst));
504 }
505 
506 //-----------------------------------------------------------------------------------------
507 // our own DlgProc because we do subclass the dialog
508 // we catch the WM_NCDESTROY message in order to erase an entry in our static map
509 // if one instance dies
510 //-----------------------------------------------------------------------------------------
511 
512 LRESULT CALLBACK CWinFileOpenImpl::SubClassFunc(
513     HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam)
514 {
515 	unsigned int lResult = 0;
516 
517     CWinFileOpenImpl* pImpl = dynamic_cast<CWinFileOpenImpl*>(getCurrentInstance(hWnd));
518 
519 	switch(wMessage)
520 	{
521 	case WM_HELP:
522 	{
523         LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
524 
525         if (pImpl->IsCustomControlHelpRequested(lphi))
526 		    pImpl->onCustomControlHelpRequest(lphi);
527         else
528             lResult = CallWindowProc(
529 			    reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
530 			    hWnd,wMessage,wParam,lParam);
531 	}
532 	break;
533 
534 	case WM_SIZE:
535 		lResult = CallWindowProc(
536 			reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
537 			hWnd,wMessage,wParam,lParam);
538 
539 		pImpl->onWMSize();
540 		break;
541 
542 	case WM_WINDOWPOSCHANGED:
543 		lResult = CallWindowProc(
544 			reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
545 			hWnd,wMessage,wParam,lParam);
546 
547 		pImpl->onWMWindowPosChanged();
548 		break;
549 
550 	case WM_SHOWWINDOW:
551 		lResult = CallWindowProc(
552 			reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
553 			hWnd,wMessage,wParam,lParam);
554 
555 		pImpl->onWMShow((sal_Bool)wParam);
556 		break;
557 
558     case WM_NCDESTROY:
559 		// restore the old window proc
560 		SetWindowLong(hWnd, GWL_WNDPROC,
561 			reinterpret_cast<LONG>(pImpl->m_pfnOldDlgProc));
562 
563 		lResult = CallWindowProc(
564 			reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
565 			hWnd,wMessage,wParam,lParam);
566 		break;
567 
568 	default:
569 		lResult = CallWindowProc(
570 			reinterpret_cast<WNDPROC>(pImpl->m_pfnOldDlgProc),
571 			hWnd,wMessage,wParam,lParam);
572 	break;
573 
574 	} // switch
575 
576 	return lResult;
577 }
578 
579 //-----------------------------------------------------------------
580 //
581 //-----------------------------------------------------------------
582 
583 void SAL_CALL CWinFileOpenImpl::InitControlLabel(HWND hWnd)
584 {
585     //-----------------------------------------
586     // set the labels for all extendet controls
587     //-----------------------------------------
588 
589     sal_Int16 aCtrlId = sal::static_int_cast< sal_Int16 >(GetDlgCtrlID(hWnd));
590     rtl::OUString aLabel = m_ResProvider.getResString(aCtrlId);
591     if (aLabel.getLength())
592         setLabel(aCtrlId, aLabel);
593 }
594 
595 //-----------------------------------------------------------------
596 // There may be problems with the layout of our custom controls,
597 // so that they are not aligned with the standard controls of the
598 // FileOpen dialog.
599 // We use a simple algorithm to move the custom controls to their
600 // proper position and resize them.
601 // Our approach is to align all static text controls with the
602 // static text control "File name" of the FileOpen dialog,
603 // all checkboxes and all list/comboboxes will be left aligned with
604 // the standard combobox edt1 (defined in MS platform sdk dlgs.h)
605 // and all push buttons will be left aligned with the standard
606 // "OK" button
607 //-----------------------------------------------------------------
608 
609 void SAL_CALL CWinFileOpenImpl::InitCustomControlContainer(HWND hCustomControl)
610 {
611 	m_CustomControls->AddControl(
612 		m_CustomControlFactory->CreateCustomControl(hCustomControl,m_hwndFileOpenDlg));
613 }
614 
615 //-----------------------------------------------------------------
616 //
617 //-----------------------------------------------------------------
618 
619 void SAL_CALL CWinFileOpenImpl::CacheControlState(HWND hWnd)
620 {
621     OSL_ASSERT(m_FilePickerState && m_NonExecuteFilePickerState);
622     m_ExecuteFilePickerState->cacheControlState(hWnd, m_NonExecuteFilePickerState);
623 }
624 
625 //-----------------------------------------------------------------
626 //
627 //-----------------------------------------------------------------
628 
629 BOOL CALLBACK CWinFileOpenImpl::EnumChildWndProc(HWND hWnd, LPARAM lParam)
630 {
631     EnumParam* enumParam    = (EnumParam*)lParam;
632     CWinFileOpenImpl* pImpl = enumParam->m_instance;
633 
634     OSL_ASSERT(pImpl);
635 
636     sal_Bool bRet = sal_True;
637 
638     switch(enumParam->m_action)
639     {
640     case INIT_CUSTOM_CONTROLS:
641         pImpl->InitControlLabel(hWnd);
642 		pImpl->InitCustomControlContainer(hWnd);
643 		break;
644 
645     case CACHE_CONTROL_VALUES:
646         pImpl->CacheControlState(hWnd);
647     break;
648 
649     default:
650         // should not end here
651         OSL_ASSERT(sal_False);
652     }
653 
654     return bRet;
655 }
656 
657 //-----------------------------------------------------------------
658 //
659 //-----------------------------------------------------------------
660 
661 sal_uInt32 SAL_CALL CWinFileOpenImpl::onFileOk()
662 {
663     m_NonExecuteFilePickerState->reset();
664 
665     EnumParam enumParam(CACHE_CONTROL_VALUES,this);
666 
667     EnumChildWindows(
668 		m_hwndFileOpenDlgChild,
669 		CWinFileOpenImpl::EnumChildWndProc,
670 		(LPARAM)&enumParam);
671 
672 	return 0;
673 }
674 
675 //-----------------------------------------------------------------
676 //
677 //-----------------------------------------------------------------
678 
679 void SAL_CALL CWinFileOpenImpl::onSelChanged(HWND)
680 {
681     // the windows file open dialog sends an initial
682     // SelChanged message after the InitDone message
683     // when the dialog is about to be opened
684     // if the lpstrFile buffer of the OPENFILENAME is
685     // empty (zero length string) the windows file open
686     // dialog sends a WM_SETTEXT message with an empty
687     // string to the file name edit line
688     // this would overwritte our text when we would set
689     // the default name in onInitDone, so we have to
690     // remeber that this is the first SelChanged message
691     // and set the default name here to overwrite the
692     // windows setting
693     InitialSetDefaultName();
694 
695 	FilePickerEvent evt;
696 	m_FilePicker->fileSelectionChanged(evt);
697 }
698 
699 // #i40865# The size of the standard labels 'File name'
700 // and 'File type' is to short in some cases when the
701 // label will be changed (e.g. in the Brazil version).
702 // We just make sure that the labels are using the maximum
703 // available space.
704 void CWinFileOpenImpl::EnlargeStdControlLabels() const
705 {
706     HWND hFilterBoxLabel = GetDlgItem(m_hwndFileOpenDlg, stc2);
707     HWND hFileNameBoxLabel = GetDlgItem(m_hwndFileOpenDlg, stc3);
708     HWND hFileNameBox = GetDlgItem(m_hwndFileOpenDlg, cmb13);
709     if (!hFileNameBox)
710         hFileNameBox = GetDlgItem(m_hwndFileOpenDlg, edt1); // under Win98 it is edt1 instead of cmb13
711 
712     HWND hFilterBox = GetDlgItem(m_hwndFileOpenDlg, cmb1);
713     HWND hOkButton = GetDlgItem(m_hwndFileOpenDlg, IDOK);
714 
715     // Move filter and file name box nearer to OK and Cancel button
716     RECT rcOkButton;
717     GetWindowRect(hOkButton, &rcOkButton);
718 
719     const int MAX_GAP = IsWindows98() ? 5 : 10;
720     const int OFFSET = IsWindows98() ? 10 : 0;
721 
722     RECT rcFileNameBox;
723     GetWindowRect(hFileNameBox, &rcFileNameBox);
724     int w = rcFileNameBox.right - rcFileNameBox.left;
725     int h = rcFileNameBox.bottom - rcFileNameBox.top;
726 
727     int gap = rcOkButton.left - rcFileNameBox.right;
728     gap = (gap > MAX_GAP) ? gap - MAX_GAP : gap;
729 
730     ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFileNameBox);
731     MoveWindow(hFileNameBox, rcFileNameBox.left + gap + OFFSET, rcFileNameBox.top, w - OFFSET, h, true);
732 
733     RECT rcFilterBox;
734     GetWindowRect(hFilterBox, &rcFilterBox);
735     w = rcFilterBox.right - rcFilterBox.left;
736     h = rcFilterBox.bottom - rcFilterBox.top;
737     ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFilterBox);
738     MoveWindow(hFilterBox, rcFilterBox.left + gap + OFFSET, rcFilterBox.top, w - OFFSET, h, true);
739 
740     // get the new window rect
741     GetWindowRect(hFileNameBox, &rcFileNameBox);
742 
743     RECT rcFilterBoxLabel;
744     GetWindowRect(hFilterBoxLabel, &rcFilterBoxLabel);
745     int offset = rcFileNameBox.left - rcFilterBoxLabel.right - 1;
746 
747     w = rcFilterBoxLabel.right - rcFilterBoxLabel.left + offset;
748     h = rcFilterBoxLabel.bottom - rcFilterBoxLabel.top;
749     ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFilterBoxLabel);
750     MoveWindow(hFilterBoxLabel, rcFilterBoxLabel.left, rcFilterBoxLabel.top, w, h, true);
751 
752     RECT rcFileNameBoxLabel;
753     GetWindowRect(hFileNameBoxLabel, &rcFileNameBoxLabel);
754     w = rcFileNameBoxLabel.right - rcFileNameBoxLabel.left + offset;
755     h = rcFileNameBoxLabel.bottom - rcFileNameBoxLabel.top;
756     ScreenToClient(m_hwndFileOpenDlg, (LPPOINT)&rcFileNameBoxLabel);
757     MoveWindow(hFileNameBoxLabel, rcFileNameBoxLabel.left, rcFileNameBoxLabel.top, w, h, true);
758 }
759 
760 void SAL_CALL CWinFileOpenImpl::onInitDone()
761 {
762 	m_Preview->setParent(m_hwndFileOpenDlg);
763 
764 	// but now we have a valid parent handle
765     m_HelpPopupWindow.setParent(m_hwndFileOpenDlg);
766 
767     EnlargeStdControlLabels();
768 
769     // #99826
770     // Set the online filepicker state before initializing
771     // the control labels from the resource else we are
772     // overriding the offline settings
773     m_ExecuteFilePickerState->setHwnd(m_hwndFileOpenDlgChild);
774 
775     m_FilePickerState = m_ExecuteFilePickerState;
776 
777     // initialize controls from cache
778 
779     EnumParam enumParam(INIT_CUSTOM_CONTROLS,this);
780 
781     EnumChildWindows(
782 		m_hwndFileOpenDlgChild,
783 		CWinFileOpenImpl::EnumChildWndProc,
784 		(LPARAM)&enumParam);
785 
786     m_ExecuteFilePickerState->initFilePickerControls(
787         m_NonExecuteFilePickerState->getControlCommand());
788 
789     SetDefaultExtension();
790 
791 	m_CustomControls->Align();
792 
793 	m_CustomControls->SetFont(
794 		reinterpret_cast<HFONT>(SendMessage(m_hwndFileOpenDlg, WM_GETFONT, 0, 0)));
795 
796     // resume event notification that was
797     // defered in onInitDialog
798     m_FilePicker->resumeEventNotification();
799 
800     //#105996 let vcl know that now a system window is active
801     PostMessage(
802         HWND_BROADCAST,
803         RegisterWindowMessage(TEXT("SYSTEM_WINDOW_ACTIVATED")),
804         0,
805         0);
806 
807     // call the parent function to center the
808     // dialog to it's parent
809     CFileOpenDialog::onInitDone();
810 }
811 
812 //-----------------------------------------------------------------
813 //
814 //-----------------------------------------------------------------
815 
816 void SAL_CALL CWinFileOpenImpl::onFolderChanged()
817 {
818 	FilePickerEvent evt;
819 	m_FilePicker->directoryChanged(evt);
820 }
821 
822 //-----------------------------------------------------------------
823 //
824 //-----------------------------------------------------------------
825 
826 void SAL_CALL CWinFileOpenImpl::onTypeChanged(sal_uInt32)
827 {
828     SetDefaultExtension();
829 
830     FilePickerEvent evt;
831     evt.ElementId = LISTBOX_FILTER;
832     m_FilePicker->controlStateChanged(evt);
833 }
834 
835 //-----------------------------------------------------------------------------------------
836 // onMessageCommand handler
837 //-----------------------------------------------------------------------------------------
838 
839 sal_uInt32 SAL_CALL CWinFileOpenImpl::onCtrlCommand(
840 	HWND, sal_uInt16 ctrlId, sal_uInt16)
841 {
842     SetDefaultExtension();
843 
844     if (ctrlId < ctlFirst)
845     {
846 	    FilePickerEvent evt;
847         evt.ElementId = ctrlId;
848         m_FilePicker->controlStateChanged(evt);
849     }
850 
851 	return 0;
852 }
853 
854 //-----------------------------------------------------------------------------------------
855 //
856 //-----------------------------------------------------------------------------------------
857 
858 void CWinFileOpenImpl::onWMSize()
859 {
860 	m_Preview->notifyParentSizeChanged();
861 	m_CustomControls->Align();
862 	m_FilePicker->dialogSizeChanged();
863 }
864 
865 //-----------------------------------------------------------------------------------------
866 //
867 //-----------------------------------------------------------------------------------------
868 
869 void CWinFileOpenImpl::onWMShow(sal_Bool bShow)
870 {
871 	m_Preview->notifyParentShow(bShow);
872 }
873 
874 //-----------------------------------------------------------------------------------------
875 //
876 //-----------------------------------------------------------------------------------------
877 
878 void CWinFileOpenImpl::onWMWindowPosChanged()
879 {
880 	m_Preview->notifyParentWindowPosChanged();
881 }
882 
883 //-----------------------------------------------------------------------------------------
884 //
885 //-----------------------------------------------------------------------------------------
886 
887 void CWinFileOpenImpl::onCustomControlHelpRequest(LPHELPINFO lphi)
888 {
889 	FilePickerEvent evt;
890     evt.ElementId = sal::static_int_cast< sal_Int16 >(lphi->iCtrlId);
891 
892 	rtl::OUString aPopupHelpText = m_FilePicker->helpRequested(evt);
893 
894     if (aPopupHelpText.getLength())
895     {
896 		m_HelpPopupWindow.setText(aPopupHelpText);
897 
898         DWORD dwMsgPos = GetMessagePos();
899         m_HelpPopupWindow.show(LOWORD(dwMsgPos),HIWORD(dwMsgPos));
900     }
901 }
902 
903 //-----------------------------------------------------------------------------------------
904 //
905 //-----------------------------------------------------------------------------------------
906 
907 void SAL_CALL CWinFileOpenImpl::onInitDialog(HWND hwndDlg)
908 {
909 	// subclass the dialog window
910 	m_pfnOldDlgProc =
911 		reinterpret_cast<WNDPROC>(
912 			SetWindowLong( hwndDlg, GWL_WNDPROC,
913 			reinterpret_cast<LONG>(SubClassFunc)));
914 }
915 
916 //-----------------------------------------------------------------------------------------
917 // processing before showing the dialog
918 //-----------------------------------------------------------------------------------------
919 
920 bool SAL_CALL CWinFileOpenImpl::preModal()
921 {
922 	CFileOpenDialog::setFilter(
923 		makeWinFilterBuffer(*m_filterContainer.get()));
924 
925 	return true;
926 }
927 
928 //-----------------------------------------------------------------------------------------
929 // processing after showing the dialog
930 //-----------------------------------------------------------------------------------------
931 
932 void CWinFileOpenImpl::postModal(sal_Int16 nDialogResult)
933 {
934 	CFileOpenDialog::postModal(nDialogResult);
935 
936 	// empty the container in order to get rid off
937 	// invalid controls in case someone calls execute
938 	// twice in sequence with the same instance
939 	m_CustomControls->RemoveAllControls();
940 
941     m_FilePickerState = m_NonExecuteFilePickerState;
942 }
943 
944 //-----------------------------------------------------------------------------------------
945 //
946 //-----------------------------------------------------------------------------------------
947 
948 void SAL_CALL CWinFileOpenImpl::SetDefaultExtension()
949 {
950     HWND hwndChkSaveWithExt = GetDlgItem(m_hwndFileOpenDlgChild, 100);
951 
952     if (hwndChkSaveWithExt)
953     {
954 		uno::Any aAny = CheckboxGetState(hwndChkSaveWithExt);
955         sal_Bool bChecked = *reinterpret_cast<const sal_Bool*>(aAny.getValue());
956 
957         if (bChecked)
958         {
959             sal_uInt32 nIndex = getSelectedFilterIndex();
960 
961 	        rtl::OUString currentFilter;
962 	        if (nIndex > 0)
963 	        {
964 		        // filter index of the base class starts with 1
965 		        m_filterContainer->getFilter(nIndex - 1, currentFilter);
966 
967                 if (currentFilter.getLength())
968                 {
969 		            rtl::OUString FilterExt;
970                     m_filterContainer->getFilter(currentFilter, FilterExt);
971 
972                     sal_Int32 posOfPoint = FilterExt.indexOf(L'.');
973                     const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1;
974 
975                     sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1;
976                     if (posOfSemiColon < 0)
977                         posOfSemiColon = FilterExt.getLength() - 1;
978 
979                     FilterExt = rtl::OUString(pFirstExtStart, posOfSemiColon - posOfPoint);
980 
981                     SendMessage(m_hwndFileOpenDlg, CDM_SETDEFEXT, 0, reinterpret_cast<LPARAM>(FilterExt.getStr()));
982                  }
983 	        }
984         }
985         else
986         {
987             SendMessage(m_hwndFileOpenDlg, CDM_SETDEFEXT, 0, reinterpret_cast<LPARAM>(TEXT("")));
988         }
989     }
990 
991     // !!! HACK !!!
992 }
993 
994 //-----------------------------------------------------------------------------------------
995 //
996 //-----------------------------------------------------------------------------------------
997 
998 void SAL_CALL CWinFileOpenImpl::InitialSetDefaultName()
999 {
1000     // manually setting the file name that appears
1001     // initially in the file-name-box of the file
1002     // open dialog (reason: see above setDefaultName)
1003     if (m_bInitialSelChanged && m_defaultName.getLength())
1004     {
1005         sal_Int32 edt1Id = edt1;
1006 
1007         // under W2k the there is a combobox instead
1008         // of an edit field for the file name edit field
1009         // the control id of this box is cmb13 and not
1010         // edt1 as before so we must use this id
1011         if (IsWindows2000Platform())
1012             edt1Id = cmb13;
1013 
1014         HWND hwndEdt1 = GetDlgItem(m_hwndFileOpenDlg, edt1Id);
1015         SetWindowText(hwndEdt1, reinterpret_cast<LPCTSTR>(m_defaultName.getStr()));
1016     }
1017 
1018     m_bInitialSelChanged = sal_False;
1019 }
1020