summaryrefslogtreecommitdiffstats
path: root/fpicker/source/win32
diff options
context:
space:
mode:
Diffstat (limited to 'fpicker/source/win32')
-rw-r--r--fpicker/source/win32/FPServiceInfo.hxx37
-rw-r--r--fpicker/source/win32/FPentry.cxx97
-rw-r--r--fpicker/source/win32/FilterContainer.cxx275
-rw-r--r--fpicker/source/win32/FilterContainer.hxx110
-rw-r--r--fpicker/source/win32/IVistaFilePickerInternalNotify.hxx58
-rw-r--r--fpicker/source/win32/VistaFilePicker.cxx555
-rw-r--r--fpicker/source/win32/VistaFilePicker.hxx240
-rw-r--r--fpicker/source/win32/VistaFilePickerEventHandler.cxx332
-rw-r--r--fpicker/source/win32/VistaFilePickerEventHandler.hxx195
-rw-r--r--fpicker/source/win32/VistaFilePickerImpl.cxx1333
-rw-r--r--fpicker/source/win32/VistaFilePickerImpl.hxx337
-rw-r--r--fpicker/source/win32/WinImplHelper.cxx163
-rw-r--r--fpicker/source/win32/WinImplHelper.hxx53
-rw-r--r--fpicker/source/win32/asyncrequests.cxx227
-rw-r--r--fpicker/source/win32/asyncrequests.hxx214
-rw-r--r--fpicker/source/win32/comptr.hxx212
-rw-r--r--fpicker/source/win32/fps.component27
-rw-r--r--fpicker/source/win32/platform_vista.h46
-rw-r--r--fpicker/source/win32/resourceprovider.cxx103
-rw-r--r--fpicker/source/win32/resourceprovider.hxx39
-rw-r--r--fpicker/source/win32/shared.hxx31
-rw-r--r--fpicker/source/win32/vistatypes.h47
-rw-r--r--fpicker/source/win32/workbench/Test_fps.cxx356
-rw-r--r--fpicker/source/win32/workbench/makefile.mk55
24 files changed, 5142 insertions, 0 deletions
diff --git a/fpicker/source/win32/FPServiceInfo.hxx b/fpicker/source/win32/FPServiceInfo.hxx
new file mode 100644
index 000000000..edc350c1a
--- /dev/null
+++ b/fpicker/source/win32/FPServiceInfo.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_FPSERVICEINFO_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_FPSERVICEINFO_HXX
+
+// the service names
+#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.SystemFilePicker"
+
+// the implementation names
+#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.Win32FilePicker"
+
+// the service names
+#define FOLDER_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.SystemFolderPicker"
+
+// the implementation names
+#define FOLDER_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.Win32FolderPicker"
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/FPentry.cxx b/fpicker/source/win32/FPentry.cxx
new file mode 100644
index 000000000..a4e48f886
--- /dev/null
+++ b/fpicker/source/win32/FPentry.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppuhelper/factory.hxx>
+#include <com/sun/star/container/XSet.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include "FPServiceInfo.hxx"
+
+#include "VistaFilePicker.hxx"
+#include "WinImplHelper.hxx"
+#include <stdio.h>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::cppu;
+using ::com::sun::star::ui::dialogs::XFilePicker2;
+using ::com::sun::star::ui::dialogs::XFolderPicker2;
+
+static Reference< XInterface > createInstance(
+ const Reference< XMultiServiceFactory >& rServiceManager )
+{
+ return Reference<ui::dialogs::XFilePicker2>(
+ new ::fpicker::win32::vista::VistaFilePicker(rServiceManager, false));
+}
+
+static Reference< XInterface >
+createInstance_fop( const Reference< XMultiServiceFactory >& rServiceManager )
+{
+ return Reference<ui::dialogs::XFolderPicker2>(
+ new ::fpicker::win32::vista::VistaFilePicker(rServiceManager, true));
+}
+
+extern "C"
+{
+
+SAL_DLLPUBLIC_EXPORT void* fps_win32_component_getFactory(
+ const char* pImplName, void* pSrvManager, void* )
+{
+ void* pRet = nullptr;
+
+ if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, FILE_PICKER_IMPL_NAME ) ) )
+ {
+ Sequence<OUString> aSNS { FILE_PICKER_SERVICE_NAME };
+
+ Reference< XSingleServiceFactory > xFactory ( createSingleFactory(
+ static_cast< XMultiServiceFactory* > ( pSrvManager ),
+ OUString::createFromAscii( pImplName ),
+ createInstance,
+ aSNS ) );
+ if ( xFactory.is() )
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+ }
+
+ if ( pSrvManager && ( 0 == rtl_str_compare( pImplName, FOLDER_PICKER_IMPL_NAME ) ) )
+ {
+ Sequence<OUString> aSNS { FOLDER_PICKER_SERVICE_NAME };
+
+ Reference< XSingleServiceFactory > xFactory ( createSingleFactory(
+ static_cast< XMultiServiceFactory* > ( pSrvManager ),
+ OUString::createFromAscii( pImplName ),
+ createInstance_fop,
+ aSNS ) );
+ if ( xFactory.is() )
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+ }
+
+ return pRet;
+}
+
+} // extern "C"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/FilterContainer.cxx b/fpicker/source/win32/FilterContainer.cxx
new file mode 100644
index 000000000..67ccd6353
--- /dev/null
+++ b/fpicker/source/win32/FilterContainer.cxx
@@ -0,0 +1,275 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <algorithm>
+#include <memory>
+#include <stdexcept>
+#include <osl/diagnose.h>
+#include "FilterContainer.hxx"
+
+#include <utility>
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+CFilterContainer::CFilterContainer( sal_Int32 initSize ) :
+ m_vFilters( initSize ),
+ m_bIterInitialized( false )
+{
+}
+
+// add a name/filter pair
+
+bool CFilterContainer::addFilter(
+ const OUString& aName, const OUString& aFilter, bool bAllowDuplicates )
+{
+ // check if the filter is already in the container
+ sal_Int32 pos = -1;
+
+ if ( !bAllowDuplicates )
+ {
+ pos = getFilterTagPos( aName );
+ if ( pos < 0 ) // if not there, append
+ {
+ m_vFilters.push_back( std::make_pair( aName, aFilter ) );
+ m_bIterInitialized = false;
+ }
+ }
+ else
+ {
+ m_vFilters.push_back( std::make_pair( aName, aFilter ) );
+ m_bIterInitialized = false;
+ }
+
+ return pos < 0;
+}
+
+// delete a filter
+// Precondition: the container is not empty
+// there is a filter identified by the given name
+
+bool CFilterContainer::delFilter( const OUString& aName )
+{
+ OSL_ASSERT( !m_vFilters.empty() );
+
+ sal_Int32 pos = getFilterTagPos( aName );
+ if ( pos > -1 )
+ {
+ m_vFilters.erase( m_vFilters.begin() + pos );
+ m_bIterInitialized = false;
+ }
+
+ return pos > -1;
+}
+
+// return the number of filters currently in the container
+
+sal_Int32 CFilterContainer::numFilter( )
+{
+ return m_vFilters.size( );
+}
+
+// clear all entries
+
+void CFilterContainer::empty()
+{
+ m_vFilters.clear( );
+}
+
+// get a filter by name
+// Precondition: the container is not empty
+// there is a filter identified by the name
+
+bool CFilterContainer::getFilterByName(const OUString& aName, OUString& theFilter) const
+{
+ OSL_PRECOND( !m_vFilters.empty() , "Empty filter container" );
+ return getFilterByIndex(getFilterTagPos(aName), theFilter);
+}
+
+bool CFilterContainer::getFilterByIndex(sal_Int32 aIndex, OUString& theFilter) const
+{
+ bool bRet = true;
+
+ try
+ {
+ theFilter = m_vFilters.at(aIndex).second;
+ }
+ catch (std::out_of_range&)
+ {
+ OSL_FAIL("Filter index out of range");
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+bool CFilterContainer::getFilterNameByIndex(sal_Int32 aIndex, OUString& theName) const
+{
+ bool bRet = true;
+
+ try
+ {
+ theName = m_vFilters.at(aIndex).first;
+ }
+ catch( std::out_of_range& )
+ {
+ OSL_FAIL( "Filter index out of range" );
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+sal_Int32 CFilterContainer::getFilterPos( const OUString& aName ) const
+{
+ return getFilterTagPos( aName );
+}
+
+// returns the index of the filter identified by name
+
+sal_Int32 CFilterContainer::getFilterTagPos( const OUString& aName ) const
+{
+ if ( !m_vFilters.empty() )
+ {
+ FILTER_VECTOR_T::const_iterator iter = std::find_if(m_vFilters.begin(), m_vFilters.end(),
+ [&aName](const FILTER_ENTRY_T& rFilter) { return rFilter.first.equalsIgnoreAsciiCase(aName); });
+ if (iter != m_vFilters.end())
+ return std::distance(m_vFilters.begin(), iter);
+ }
+
+ return -1;
+}
+
+// starts enumerating the filter in the container
+
+void CFilterContainer::beginEnumFilter( )
+{
+ m_iter = m_vFilters.begin( );
+ m_bIterInitialized = true;
+}
+
+// returns true if another filter has been retrieved
+
+bool CFilterContainer::getNextFilter( FILTER_ENTRY_T& nextFilterEntry )
+{
+ OSL_ASSERT( m_bIterInitialized );
+
+ bool bRet = ( m_iter != m_vFilters.end( ) );
+
+ if ( bRet )
+ nextFilterEntry = *m_iter++;
+ else
+ m_bIterInitialized = false;
+
+ return bRet;
+}
+
+void CFilterContainer::setCurrentFilter( const OUString& aName )
+{
+ m_sCurrentFilter = aName;
+}
+
+OUString CFilterContainer::getCurrentFilter() const
+{
+ return m_sCurrentFilter;
+}
+
+// calculates the length of a '\0' separated filter, that means
+// length of the name + '\0' + length of the filter string +
+// a trailing '\0'
+
+static sal_uInt32 getLengthFilter( CFilterContainer::FILTER_ENTRY_T aFilterEntry )
+{
+ return (
+ aFilterEntry.first.getLength( ) + 1 +
+ aFilterEntry.second.getLength( ) + 1 );
+}
+
+// calculates the length of all filters currently in the container
+
+static sal_uInt32 getTotalFilterLength( CFilterContainer& aFilterContainer )
+{
+ CFilterContainer::FILTER_ENTRY_T nextFilter;
+
+ aFilterContainer.beginEnumFilter( );
+
+ sal_uInt32 totalLength = 0;
+ while( aFilterContainer.getNextFilter( nextFilter ) )
+ totalLength += getLengthFilter( nextFilter );
+
+ return ( totalLength > 0 ) ? totalLength + 1 : totalLength;
+}
+
+static
+void wcsmemcpy( sal_Unicode* pDest, const sal_Unicode* pSrc, sal_uInt32 nLength )
+{
+ memcpy( pDest, pSrc, nLength * sizeof( sal_Unicode ) );
+}
+
+// a helper trivial helper function to create a filter buffer in the
+// format the Win32 API requires,
+// e.g. "Text\0*.txt\0Doc\0*.doc;*xls\0\0"
+
+OUString makeWinFilterBuffer( CFilterContainer& aFilterContainer )
+{
+ // calculate the required buffer size
+ sal_uInt32 reqBuffSize = getTotalFilterLength( aFilterContainer );
+
+ // return if there are no filters
+ if ( !reqBuffSize )
+ return OUString( );
+
+ auto pBuff = std::make_unique<sal_Unicode[]>(reqBuffSize);
+
+ // initialize the buffer with 0
+ ZeroMemory( pBuff.get(), sizeof( sal_Unicode ) * reqBuffSize );
+
+ OUString winFilterBuff;
+ CFilterContainer::FILTER_ENTRY_T nextFilter;
+ sal_uInt32 memPos = 0;
+
+ aFilterContainer.beginEnumFilter( );
+
+ while( aFilterContainer.getNextFilter( nextFilter ) )
+ {
+ wcsmemcpy(
+ pBuff.get() + memPos,
+ nextFilter.first.getStr( ),
+ nextFilter.first.getLength( ) );
+
+ memPos += nextFilter.first.getLength( ) + 1;
+
+ wcsmemcpy(
+ pBuff.get() + memPos,
+ nextFilter.second.getStr( ),
+ nextFilter.second.getLength( ) );
+
+ memPos += nextFilter.second.getLength( ) + 1 ;
+ }
+
+ winFilterBuff = OUString( pBuff.get(), reqBuffSize );
+
+ return winFilterBuff;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/FilterContainer.hxx b/fpicker/source/win32/FilterContainer.hxx
new file mode 100644
index 000000000..f54b10a7f
--- /dev/null
+++ b/fpicker/source/win32/FilterContainer.hxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_FILTERCONTAINER_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_FILTERCONTAINER_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+#include <vector>
+
+
+// helper class, only usable by OFilterContainer
+
+
+class CFilterContainer
+{
+public:
+ // defines a filter entry which is made of a name and a filter value
+ // e.g. 'Text *.txt'
+ typedef std::pair< OUString, OUString > FILTER_ENTRY_T;
+
+public:
+ explicit CFilterContainer( sal_Int32 initSize = 0 );
+
+ // add a new filter
+ // returns true if the filter was successfully added
+ // returns false if duplicates are not allowed and
+ // the filter is already in the container
+ bool addFilter(
+ const OUString& aName,
+ const OUString& aFilter,
+ bool bAllowDuplicates = false );
+
+ // delete the specified filter returns true on
+ // success and false if the filter was not found
+ bool delFilter( const OUString& aName );
+
+ // the number of filter already added
+ sal_Int32 numFilter( );
+
+ // clear all entries
+ void empty( );
+
+ // retrieve a filter from the container. These methods
+ // return true on success and false if the specified
+ // filter was not found
+ bool getFilterByName(const OUString& aName, OUString& theFilter) const;
+ bool getFilterByIndex(sal_Int32 aIndex, OUString& theFilter) const;
+ bool getFilterNameByIndex(sal_Int32 aIndex, OUString& theName) const;
+
+ // returns the position of the specified filter or -1
+ // if the filter was not found
+ sal_Int32 getFilterPos( const OUString& aName ) const;
+
+ // starts enumerating the filter in the container
+ void beginEnumFilter( );
+
+ // returns true if another filter has been retrieved
+ bool getNextFilter( FILTER_ENTRY_T& nextFilterEntry );
+
+ // cache current filter
+ void setCurrentFilter( const OUString& aName );
+
+ // returns cached current filter
+ OUString getCurrentFilter() const;
+
+protected:
+ typedef std::vector< FILTER_ENTRY_T > FILTER_VECTOR_T;
+
+private:
+ // prevent copy and assignment
+ CFilterContainer( const CFilterContainer& );
+ CFilterContainer& SAL_CALL operator=( const CFilterContainer& );
+
+ sal_Int32 getFilterTagPos( const OUString& aName ) const;
+
+private:
+ FILTER_VECTOR_T m_vFilters;
+ FILTER_VECTOR_T::const_iterator m_iter;
+ bool m_bIterInitialized;
+ OUString m_sCurrentFilter;
+};
+
+
+// a helper function to create a filter buffer in the format
+// the Win32 API requires, e.g. "Text\0*.txt\0Doc\0*.doc;*xls\0\0"
+
+
+OUString makeWinFilterBuffer( CFilterContainer& aFilterContainer );
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/IVistaFilePickerInternalNotify.hxx b/fpicker/source/win32/IVistaFilePickerInternalNotify.hxx
new file mode 100644
index 000000000..f39d5aff4
--- /dev/null
+++ b/fpicker/source/win32/IVistaFilePickerInternalNotify.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_IVISTAFILEPICKERINTERNALNOTIFY_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_IVISTAFILEPICKERINTERNALNOTIFY_HXX
+
+#include "vistatypes.h"
+
+#include <cppuhelper/basemutex.hxx>
+#include <osl/interlck.h>
+
+#include <shobjidl.h>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+// types, const etcpp.
+
+
+/** todo document me
+ */
+class IVistaFilePickerInternalNotify
+{
+ public:
+
+ virtual void onAutoExtensionChanged (bool bChecked) = 0;
+
+ virtual bool onFileTypeChanged( UINT nTypeIndex ) = 0;
+
+ virtual void onDirectoryChanged() = 0;
+
+ protected:
+ ~IVistaFilePickerInternalNotify() {}
+};
+
+}}}
+
+#endif // INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_IVISTAFILEPICKERINTERNALNOTIFY_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/VistaFilePicker.cxx b/fpicker/source/win32/VistaFilePicker.cxx
new file mode 100644
index 000000000..67c49f4d1
--- /dev/null
+++ b/fpicker/source/win32/VistaFilePicker.cxx
@@ -0,0 +1,555 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include "VistaFilePicker.hxx"
+
+#include "WinImplHelper.hxx"
+#include "FPServiceInfo.hxx"
+#include "shared.hxx"
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/processfactory.hxx>
+#include <osl/mutex.hxx>
+#include <osl/file.hxx>
+#include <officecfg/Office/Common.hxx>
+
+#include <shlobj.h>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+namespace
+{
+ css::uno::Sequence< OUString > VistaFilePicker_getSupportedServiceNames()
+ {
+ return {
+ "com.sun.star.ui.dialogs.FilePicker",
+ "com.sun.star.ui.dialogs.SystemFilePicker",
+ "com.sun.star.ui.dialogs.SystemFolderPicker" };
+ }
+}
+
+VistaFilePicker::VistaFilePicker(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR, bool bFolderPicker)
+ : TVistaFilePickerBase (m_aMutex )
+ , m_xSMGR (xSMGR )
+ , m_rDialog (std::make_shared<VistaFilePickerImpl>())
+ , m_aAsyncExecute (m_rDialog )
+ , m_nFilePickerThreadId (0 )
+ , m_bInitialized (false )
+ , m_bFolderPicker (bFolderPicker )
+{
+}
+
+VistaFilePicker::~VistaFilePicker()
+{
+}
+
+void SAL_CALL VistaFilePicker::addFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener)
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_ADD_PICKER_LISTENER);
+ rRequest->setArgument(PROP_PICKER_LISTENER, xListener);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void SAL_CALL VistaFilePicker::removeFilePickerListener(const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener )
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_REMOVE_PICKER_LISTENER);
+ rRequest->setArgument(PROP_PICKER_LISTENER, xListener);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void VistaFilePicker::disposing(const css::lang::EventObject& /*aEvent*/)
+{
+}
+
+void SAL_CALL VistaFilePicker::setMultiSelectionMode(sal_Bool bMode)
+{
+ ensureInit();
+
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SET_MULTISELECTION_MODE);
+ rRequest->setArgument(PROP_MULTISELECTION_MODE, bMode);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void SAL_CALL VistaFilePicker::setTitle(const OUString& sTitle)
+{
+ ensureInit();
+
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SET_TITLE);
+ rRequest->setArgument(PROP_TITLE, sTitle);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void SAL_CALL VistaFilePicker::appendFilter(const OUString& sTitle ,
+ const OUString& sFilter)
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_APPEND_FILTER);
+ rRequest->setArgument(PROP_FILTER_TITLE, sTitle );
+ rRequest->setArgument(PROP_FILTER_VALUE, sFilter);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void SAL_CALL VistaFilePicker::setCurrentFilter(const OUString& sTitle)
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SET_CURRENT_FILTER);
+ rRequest->setArgument(PROP_FILTER_TITLE, sTitle);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+OUString SAL_CALL VistaFilePicker::getCurrentFilter()
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_GET_CURRENT_FILTER);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED);
+
+ const OUString sTitle = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, OUString());
+ return sTitle;
+}
+
+void SAL_CALL VistaFilePicker::appendFilterGroup(const OUString& /*sGroupTitle*/,
+ const css::uno::Sequence< css::beans::StringPair >& rFilters )
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_APPEND_FILTERGROUP);
+ rRequest->setArgument(PROP_FILTER_GROUP, rFilters);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void SAL_CALL VistaFilePicker::setDefaultName(const OUString& sName )
+{
+ ensureInit();
+
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SET_DEFAULT_NAME);
+ rRequest->setArgument(PROP_FILENAME, sName);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void SAL_CALL VistaFilePicker::setDisplayDirectory(const OUString& sDirectory)
+{
+ ensureInit();
+
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SET_DIRECTORY);
+ rRequest->setArgument(PROP_DIRECTORY, sDirectory);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+OUString SAL_CALL VistaFilePicker::getDisplayDirectory()
+{
+ ensureInit();
+
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_GET_DIRECTORY);
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED);
+ const OUString sDirectory = rRequest->getArgumentOrDefault(PROP_DIRECTORY, OUString());
+
+ return sDirectory;
+}
+
+// @deprecated can't be supported any longer ... see IDL description for further details
+css::uno::Sequence< OUString > SAL_CALL VistaFilePicker::getFiles()
+{
+ css::uno::Sequence< OUString > lFiles = getSelectedFiles();
+ // multiselection doesn't really work
+ // so just retrieve the first url
+ if (lFiles.getLength() > 1)
+ lFiles.realloc(1);
+ m_lLastFiles = lFiles;
+ return lFiles;
+}
+
+css::uno::Sequence< OUString > SAL_CALL VistaFilePicker::getSelectedFiles()
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_GET_SELECTED_FILES);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED);
+
+ const css::uno::Sequence< OUString > lFiles = rRequest->getArgumentOrDefault(PROP_SELECTED_FILES, css::uno::Sequence< OUString >());
+ m_lLastFiles = lFiles;
+ return lFiles;
+}
+
+void VistaFilePicker::ensureInit()
+{
+ bool bInitialized(false);
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ bInitialized = m_bInitialized;
+ }
+
+ if ( !bInitialized )
+ {
+ if (m_bFolderPicker)
+ {
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_CREATE_FOLDER_PICKER);
+ if ( ! m_aAsyncExecute.isRunning())
+ m_aAsyncExecute.create();
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ m_bInitialized = true;
+ }
+ }
+ else
+ {
+ css::uno::Sequence < css::uno::Any > aInitArguments(1);
+ aInitArguments[0] <<= css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
+ initialize(aInitArguments);
+ }
+ }
+}
+
+::sal_Int16 SAL_CALL VistaFilePicker::execute()
+{
+ ensureInit();
+
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SHOW_DIALOG_MODAL);
+
+ // if we want to show a modal window, the calling thread needs to process messages
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::PROCESS_MESSAGES);
+
+ const bool bOK = rRequest->getArgumentOrDefault(PROP_DIALOG_SHOW_RESULT, false );
+ m_lLastFiles = rRequest->getArgumentOrDefault(PROP_SELECTED_FILES , css::uno::Sequence< OUString >());
+
+ ::sal_Int16 nResult = css::ui::dialogs::ExecutableDialogResults::CANCEL;
+ if (bOK)
+ nResult = css::ui::dialogs::ExecutableDialogResults::OK;
+ return nResult;
+}
+
+// XFilePicker
+
+void SAL_CALL VistaFilePicker::setValue( ::sal_Int16 nControlId ,
+ ::sal_Int16 nControlAction,
+ const css::uno::Any& aValue )
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SET_CONTROL_VALUE);
+ rRequest->setArgument(PROP_CONTROL_ID , nControlId );
+ rRequest->setArgument(PROP_CONTROL_ACTION, nControlAction);
+ rRequest->setArgument(PROP_CONTROL_VALUE , aValue );
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+css::uno::Any SAL_CALL VistaFilePicker::getValue(::sal_Int16 nControlId ,
+ ::sal_Int16 nControlAction)
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_GET_CONTROL_VALUE);
+ rRequest->setArgument(PROP_CONTROL_ID , nControlId );
+ rRequest->setArgument(PROP_CONTROL_ACTION, nControlAction);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED);
+ return rRequest->getValue(PROP_CONTROL_VALUE);
+}
+
+void SAL_CALL VistaFilePicker::enableControl(::sal_Int16 nControlId,
+ sal_Bool bEnable )
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_ENABLE_CONTROL);
+ rRequest->setArgument(PROP_CONTROL_ID , nControlId);
+ rRequest->setArgument(PROP_CONTROL_ENABLE, bEnable );
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+void SAL_CALL VistaFilePicker::setLabel( ::sal_Int16 nControlId,
+ const OUString& sLabel )
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_SET_CONTROL_LABEL);
+ rRequest->setArgument(PROP_CONTROL_ID , nControlId);
+ rRequest->setArgument(PROP_CONTROL_LABEL, sLabel );
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+}
+
+OUString SAL_CALL VistaFilePicker::getLabel(::sal_Int16 nControlId)
+{
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (VistaFilePickerImpl::E_GET_CONTROL_LABEL);
+ rRequest->setArgument(PROP_CONTROL_ID, nControlId);
+
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::BLOCKED);
+ const OUString sLabel = rRequest->getArgumentOrDefault(PROP_CONTROL_LABEL, OUString());
+ return sLabel;
+}
+
+css::uno::Sequence< ::sal_Int16 > SAL_CALL VistaFilePicker::getSupportedImageFormats()
+{
+ return css::uno::Sequence< sal_Int16 >();
+}
+
+sal_Int32 SAL_CALL VistaFilePicker::getTargetColorDepth()
+{
+ return 0;
+}
+
+sal_Int32 SAL_CALL VistaFilePicker::getAvailableWidth()
+{
+ return 0;
+}
+
+sal_Int32 SAL_CALL VistaFilePicker::getAvailableHeight()
+{
+ return 0;
+}
+
+void SAL_CALL VistaFilePicker::setImage( sal_Int16 /*nImageFormat*/,
+ const css::uno::Any& /*aImage */)
+{
+}
+
+sal_Bool SAL_CALL VistaFilePicker::setShowState(sal_Bool /*bShowState*/)
+{
+ return false;
+}
+
+sal_Bool SAL_CALL VistaFilePicker::getShowState()
+{
+ return false;
+}
+
+void SAL_CALL VistaFilePicker::initialize(const css::uno::Sequence< css::uno::Any >& lArguments)
+{
+ if (lArguments.getLength() < 1)
+ throw css::lang::IllegalArgumentException(
+ "XInitialization::initialize() called without arguments.",
+ static_cast< css::ui::dialogs::XFilePicker2* >( this ),
+ 1);
+
+ sal_Int32 nTemplate = -1;
+ lArguments[0] >>= nTemplate;
+
+ bool bFileOpenDialog = true;
+ ::sal_Int32 nFeatures = 0;
+
+ switch(nTemplate)
+ {
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE :
+ {
+ bFileOpenDialog = true;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE :
+ {
+ bFileOpenDialog = false;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD :
+ {
+ bFileOpenDialog = false;
+ nFeatures |= FEATURE_AUTOEXTENSION;
+ nFeatures |= FEATURE_PASSWORD;
+ nFeatures |= FEATURE_GPGPASSWORD;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS :
+ {
+ bFileOpenDialog = false;
+ nFeatures |= FEATURE_AUTOEXTENSION;
+ nFeatures |= FEATURE_PASSWORD;
+ nFeatures |= FEATURE_FILTEROPTIONS;
+ nFeatures |= FEATURE_GPGPASSWORD;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION :
+ {
+ bFileOpenDialog = false;
+ nFeatures |= FEATURE_AUTOEXTENSION;
+ nFeatures |= FEATURE_SELECTION;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE :
+ {
+ bFileOpenDialog = false;
+ nFeatures |= FEATURE_AUTOEXTENSION;
+ nFeatures |= FEATURE_TEMPLATE;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE :
+ {
+ bFileOpenDialog = true;
+ nFeatures |= FEATURE_LINK;
+ nFeatures |= FEATURE_PREVIEW;
+ nFeatures |= FEATURE_IMAGETEMPLATE;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR :
+ {
+ bFileOpenDialog = true;
+ nFeatures |= FEATURE_LINK;
+ nFeatures |= FEATURE_PREVIEW;
+ nFeatures |= FEATURE_IMAGEANCHOR;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY :
+ {
+ bFileOpenDialog = true;
+ nFeatures |= FEATURE_PLAY;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PLAY :
+ {
+ bFileOpenDialog = true;
+ nFeatures |= FEATURE_LINK;
+ nFeatures |= FEATURE_PLAY;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION :
+ {
+ bFileOpenDialog = true;
+ nFeatures |= FEATURE_READONLY;
+ nFeatures |= FEATURE_VERSION;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW :
+ {
+ bFileOpenDialog = true;
+ nFeatures |= FEATURE_LINK;
+ nFeatures |= FEATURE_PREVIEW;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION :
+ {
+ bFileOpenDialog = false;
+ nFeatures |= FEATURE_AUTOEXTENSION;
+ }
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_PREVIEW :
+ {
+ bFileOpenDialog = true;
+ nFeatures |= FEATURE_PREVIEW;
+ }
+ break;
+ }
+ css::uno::Reference<css::awt::XWindow> xParentWindow;
+ if(lArguments.getLength() > 1)
+ {
+ lArguments[1] >>= xParentWindow;
+ }
+ RequestRef rRequest = std::make_shared<Request>();
+ if (bFileOpenDialog)
+ rRequest->setRequest (VistaFilePickerImpl::E_CREATE_OPEN_DIALOG);
+ else
+ rRequest->setRequest (VistaFilePickerImpl::E_CREATE_SAVE_DIALOG);
+ rRequest->setArgument(PROP_FEATURES, nFeatures);
+ rRequest->setArgument(PROP_TEMPLATE_DESCR, nTemplate);
+ if(xParentWindow.is())
+ rRequest->setArgument(PROP_PARENT_WINDOW, xParentWindow);
+ if ( ! m_aAsyncExecute.isRunning())
+ m_aAsyncExecute.create();
+ m_aAsyncExecute.triggerRequestThreadAware(rRequest, AsyncRequests::NON_BLOCKED);
+
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ m_bInitialized = true;
+ }
+}
+
+void SAL_CALL VistaFilePicker::cancel()
+{
+}
+
+OUString SAL_CALL VistaFilePicker::getDirectory()
+{
+ ensureInit();
+ css::uno::Sequence< OUString > aFileSeq = getSelectedFiles();
+ assert(aFileSeq.getLength() <= 1);
+ return aFileSeq.getLength() ? aFileSeq[0] : OUString();
+}
+
+void SAL_CALL VistaFilePicker::setDescription( const OUString& aDescription )
+{
+ setTitle(aDescription);
+}
+
+// XServiceInfo
+
+OUString SAL_CALL VistaFilePicker::getImplementationName()
+{
+ if (m_bFolderPicker)
+ return FOLDER_PICKER_IMPL_NAME;
+ else
+ return FILE_PICKER_IMPL_NAME;
+}
+
+sal_Bool SAL_CALL VistaFilePicker::supportsService(const OUString& sServiceName)
+{
+ return cppu::supportsService(this, sServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL VistaFilePicker::getSupportedServiceNames()
+{
+ return VistaFilePicker_getSupportedServiceNames();
+}
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/VistaFilePicker.hxx b/fpicker/source/win32/VistaFilePicker.hxx
new file mode 100644
index 000000000..71ccfd992
--- /dev/null
+++ b/fpicker/source/win32/VistaFilePicker.hxx
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKER_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKER_HXX
+
+#include "asyncrequests.hxx"
+#include "VistaFilePickerImpl.hxx"
+#include "VistaFilePickerEventHandler.hxx"
+
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/ui/dialogs/XFilePreview.hpp>
+#include <com/sun/star/ui/dialogs/XFolderPicker2.hpp>
+
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <rtl/ustring.hxx>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+// types
+
+
+typedef ::cppu::WeakComponentImplHelper<
+ css::ui::dialogs::XFilePicker3,
+ css::ui::dialogs::XFilePickerControlAccess,
+ css::ui::dialogs::XFilePreview,
+ css::ui::dialogs::XFolderPicker2,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo > TVistaFilePickerBase;
+
+
+/** Implements the XFilePicker & friends interface(s)
+ for Windows Vista and upcoming versions.
+
+ Note: This will be a UNO wrapper for the real file picker
+ implementation only. The real implementation is done in class
+ VistaFilePickerImpl.
+ */
+class VistaFilePicker : public ::cppu::BaseMutex
+ , public TVistaFilePickerBase
+{
+public:
+
+
+ // ctor/dtor
+
+
+ explicit VistaFilePicker( const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR, bool bFolderPicker );
+ virtual ~VistaFilePicker() override;
+
+
+ // XFilePickerNotifier
+
+
+ virtual void SAL_CALL addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) override;
+
+ virtual void SAL_CALL removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener ) override;
+
+
+ // XExecutableDialog functions
+
+
+ virtual void SAL_CALL setTitle( const OUString& sTitle ) override;
+
+ virtual sal_Int16 SAL_CALL execute( ) override;
+
+
+ // XFilePicker functions
+
+
+ virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) override;
+
+ virtual void SAL_CALL setDefaultName( const OUString& sName ) override;
+
+ virtual void SAL_CALL setDisplayDirectory( const OUString& sDirectory ) override;
+
+ virtual OUString SAL_CALL getDisplayDirectory( ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getFiles( ) override;
+
+ // XFilePicker2 functions
+ virtual css::uno::Sequence< OUString > SAL_CALL getSelectedFiles( ) override;
+
+
+ // XFilterManager functions
+
+
+ virtual void SAL_CALL appendFilter( const OUString& sTitle ,
+ const OUString& sFilter ) override;
+
+ virtual void SAL_CALL setCurrentFilter( const OUString& sTitle ) override;
+
+ virtual OUString SAL_CALL getCurrentFilter( ) override;
+
+
+ // XFilterGroupManager functions
+
+
+ virtual void SAL_CALL appendFilterGroup( const OUString& sGroupTitle,
+ const css::uno::Sequence< css::beans::StringPair >& lFilters ) override;
+
+
+ // XFilePickerControlAccess functions
+
+
+ virtual void SAL_CALL setValue( sal_Int16 nControlId ,
+ sal_Int16 nControlAction,
+ const css::uno::Any& aValue ) override;
+
+ virtual css::uno::Any SAL_CALL getValue( sal_Int16 nControlId ,
+ sal_Int16 nControlAction ) override;
+
+ virtual void SAL_CALL enableControl( sal_Int16 nControlId,
+ sal_Bool bEnable ) override;
+
+ virtual void SAL_CALL setLabel( sal_Int16 nControlId,
+ const OUString& sLabel ) override;
+
+ virtual OUString SAL_CALL getLabel( sal_Int16 nControlId ) override;
+
+
+ // XFilePreview
+
+
+ virtual css::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) override;
+
+ virtual sal_Int32 SAL_CALL getTargetColorDepth( ) override;
+
+ virtual sal_Int32 SAL_CALL getAvailableWidth( ) override;
+
+ virtual sal_Int32 SAL_CALL getAvailableHeight( ) override;
+
+ virtual void SAL_CALL setImage( sal_Int16 nImageFormat,
+ const css::uno::Any& aImage ) override;
+
+ virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) override;
+
+ virtual sal_Bool SAL_CALL getShowState( ) override;
+
+
+ // XInitialization
+
+
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& lArguments ) override;
+
+
+ // XCancellable
+
+
+ virtual void SAL_CALL cancel( ) override;
+
+
+ // XEventListener
+
+ /// @throws css::uno::RuntimeException
+ virtual void disposing( const css::lang::EventObject& aEvent );
+
+
+ // XServiceInfo
+
+
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+
+ // XFolderPicker functions
+
+
+ virtual OUString SAL_CALL getDirectory( ) override;
+
+ virtual void SAL_CALL setDescription( const OUString& aDescription ) override;
+
+
+ private:
+
+ // prevent copy and assignment
+ VistaFilePicker( const VistaFilePicker& );
+ VistaFilePicker& operator=( const VistaFilePicker& );
+
+ using WeakComponentImplHelperBase::disposing;
+
+ void ensureInit();
+
+ private:
+
+
+ /// service manager to create own used uno services
+ css::uno::Reference< css::lang::XMultiServiceFactory > m_xSMGR;
+
+
+ css::uno::Sequence< OUString > m_lLastFiles;
+
+
+ /** execute the COM dialog within a STA thread
+ * Must be used on the heap ... because it's implemented as OSL thread .-)
+ */
+ RequestHandlerRef m_rDialog;
+ AsyncRequests m_aAsyncExecute;
+
+
+ oslThreadIdentifier m_nFilePickerThreadId;
+
+ bool m_bInitialized;
+ const bool m_bFolderPicker;
+};
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+#endif // INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/VistaFilePickerEventHandler.cxx b/fpicker/source/win32/VistaFilePickerEventHandler.cxx
new file mode 100644
index 000000000..a116a6909
--- /dev/null
+++ b/fpicker/source/win32/VistaFilePickerEventHandler.cxx
@@ -0,0 +1,332 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include "VistaFilePickerEventHandler.hxx"
+
+#include "asyncrequests.hxx"
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
+#include <com/sun/star/util/RevisionTag.hpp>
+#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+
+#include <osl/file.hxx>
+
+
+// namespace directives
+
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+VistaFilePickerEventHandler::VistaFilePickerEventHandler(IVistaFilePickerInternalNotify* pInternalNotify)
+ : m_nRefCount (0 )
+ , m_nListenerHandle (0 )
+ , m_pDialog ( )
+ , m_pInternalNotify (pInternalNotify)
+ , m_lListener (m_aMutex)
+{
+}
+
+
+VistaFilePickerEventHandler::~VistaFilePickerEventHandler()
+{
+}
+
+
+HRESULT STDMETHODCALLTYPE VistaFilePickerEventHandler::QueryInterface(REFIID rIID ,
+ void** ppObject)
+{
+ *ppObject=nullptr;
+
+ if ( rIID == IID_IUnknown )
+ *ppObject = static_cast<IUnknown*>(static_cast<IFileDialogEvents*>(this));
+
+ if ( rIID == IID_IFileDialogEvents )
+ *ppObject = static_cast<IFileDialogEvents*>(this);
+
+ if ( rIID == IID_IFileDialogControlEvents )
+ *ppObject = static_cast<IFileDialogControlEvents*>(this);
+
+ if ( *ppObject != nullptr )
+ {
+ static_cast<IUnknown*>(*ppObject)->AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+
+ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::AddRef()
+{
+ return osl_atomic_increment(&m_nRefCount);
+}
+
+
+ULONG STDMETHODCALLTYPE VistaFilePickerEventHandler::Release()
+{
+ ULONG nReturn = --m_nRefCount;
+ if ( m_nRefCount == 0 )
+ delete this;
+
+ return nReturn;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnFileOk(IFileDialog* /*pDialog*/)
+{
+ return E_NOTIMPL;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnFolderChanging(IFileDialog* /*pDialog*/,
+ IShellItem* /*pFolder*/)
+{
+ return E_NOTIMPL;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnFolderChange(IFileDialog* /*pDialog*/)
+{
+ impl_sendEvent(E_DIRECTORY_CHANGED, 0);
+ m_pInternalNotify->onDirectoryChanged();
+ return S_OK;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnSelectionChange(IFileDialog* /*pDialog*/)
+{
+ impl_sendEvent(E_FILE_SELECTION_CHANGED, 0);
+ return S_OK;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnShareViolation(IFileDialog* /*pDialog*/ ,
+
+ IShellItem* /*pItem*/ ,
+
+ FDE_SHAREVIOLATION_RESPONSE* /*pResponse*/)
+{
+ impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER);
+ return S_OK;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnTypeChange(IFileDialog* pDialog)
+{
+ UINT nFileTypeIndex;
+ HRESULT hResult = pDialog->GetFileTypeIndex( &nFileTypeIndex );
+
+ if ( hResult == S_OK )
+ {
+ if ( m_pInternalNotify->onFileTypeChanged( nFileTypeIndex ))
+ impl_sendEvent(E_CONTROL_STATE_CHANGED, css::ui::dialogs::CommonFilePickerElementIds::LISTBOX_FILTER);
+ }
+
+ return S_OK;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnOverwrite(IFileDialog* /*pDialog*/ ,
+ IShellItem* /*pItem*/ ,
+ FDE_OVERWRITE_RESPONSE* /*pResponse*/)
+{
+ return E_NOTIMPL;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnItemSelected(IFileDialogCustomize* /*pCustomize*/,
+
+ DWORD nIDCtl ,
+
+ DWORD /*nIDItem*/ )
+{
+
+ impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl ));
+ return S_OK;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnButtonClicked(IFileDialogCustomize* /*pCustomize*/,
+ DWORD nIDCtl )
+{
+
+ impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl));
+ return S_OK;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnCheckButtonToggled(IFileDialogCustomize* /*pCustomize*/,
+ DWORD nIDCtl ,
+ BOOL bChecked )
+{
+ if (nIDCtl == css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION)
+ m_pInternalNotify->onAutoExtensionChanged(bChecked);
+
+ impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl));
+
+ return S_OK;
+}
+
+
+STDMETHODIMP VistaFilePickerEventHandler::OnControlActivating(IFileDialogCustomize* /*pCustomize*/,
+ DWORD nIDCtl )
+{
+ impl_sendEvent(E_CONTROL_STATE_CHANGED, static_cast<sal_Int16>( nIDCtl));
+ return S_OK;
+}
+
+
+void VistaFilePickerEventHandler::addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener )
+{
+ m_lListener.addInterface(cppu::UnoType<css::ui::dialogs::XFilePickerListener>::get(), xListener);
+}
+
+
+void VistaFilePickerEventHandler::removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener )
+{
+ m_lListener.removeInterface(cppu::UnoType<css::ui::dialogs::XFilePickerListener>::get(), xListener);
+}
+
+
+void VistaFilePickerEventHandler::startListening( const TFileDialog& pBroadcaster )
+{
+ if (m_pDialog.is())
+ return;
+
+ m_pDialog = pBroadcaster;
+ m_pDialog->Advise(this, &m_nListenerHandle);
+}
+
+
+void VistaFilePickerEventHandler::stopListening()
+{
+ if (m_pDialog.is())
+ {
+ m_pDialog->Unadvise(m_nListenerHandle);
+ m_pDialog.release();
+ }
+}
+
+static const char PROP_CONTROL_ID[] = "control_id";
+static const char PROP_PICKER_LISTENER[] = "picker_listener";
+
+namespace {
+
+class AsyncPickerEvents : public RequestHandler
+{
+public:
+
+ AsyncPickerEvents()
+ {}
+
+ virtual void before() override
+ {}
+
+ virtual void doRequest(const RequestRef& rRequest) override
+ {
+ const ::sal_Int32 nEventID = rRequest->getRequest();
+ const ::sal_Int16 nControlID = rRequest->getArgumentOrDefault(PROP_CONTROL_ID, ::sal_Int16(0));
+ const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
+
+ if ( ! xListener.is())
+ return;
+
+ css::ui::dialogs::FilePickerEvent aEvent;
+ aEvent.ElementId = nControlID;
+
+ switch (nEventID)
+ {
+ case VistaFilePickerEventHandler::E_FILE_SELECTION_CHANGED :
+ xListener->fileSelectionChanged(aEvent);
+ break;
+
+ case VistaFilePickerEventHandler::E_DIRECTORY_CHANGED :
+ xListener->directoryChanged(aEvent);
+ break;
+
+ case VistaFilePickerEventHandler::E_HELP_REQUESTED :
+ xListener->helpRequested(aEvent);
+ break;
+
+ case VistaFilePickerEventHandler::E_CONTROL_STATE_CHANGED :
+ xListener->controlStateChanged(aEvent);
+ break;
+
+ case VistaFilePickerEventHandler::E_DIALOG_SIZE_CHANGED :
+ xListener->dialogSizeChanged();
+ break;
+
+ // no default here. Let compiler detect changes on enum set !
+ }
+ }
+
+ virtual void after() override
+ {}
+};
+
+}
+
+void VistaFilePickerEventHandler::impl_sendEvent( EEventType eEventType,
+ ::sal_Int16 nControlID)
+{
+ // See special handling in ~AsyncRequests for this static
+ static AsyncRequests aNotify(std::make_shared<AsyncPickerEvents>());
+
+ ::cppu::OInterfaceContainerHelper* pContainer = m_lListener.getContainer( cppu::UnoType<css::ui::dialogs::XFilePickerListener>::get());
+ if ( ! pContainer)
+ return;
+
+ ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ try
+ {
+ css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener (pIterator.next(), css::uno::UNO_QUERY);
+
+ RequestRef rRequest = std::make_shared<Request>();
+ rRequest->setRequest (eEventType);
+ rRequest->setArgument(PROP_PICKER_LISTENER, xListener);
+ if ( nControlID )
+ rRequest->setArgument(PROP_CONTROL_ID, nControlID);
+
+ aNotify.triggerRequestDirectly(rRequest);
+ //aNotify.triggerRequestNonBlocked(rRequest);
+ }
+ catch(const css::uno::RuntimeException&)
+ {
+ pIterator.remove();
+ }
+ }
+}
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/VistaFilePickerEventHandler.hxx b/fpicker/source/win32/VistaFilePickerEventHandler.hxx
new file mode 100644
index 000000000..3ea47dbd8
--- /dev/null
+++ b/fpicker/source/win32/VistaFilePickerEventHandler.hxx
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKEREVENTHANDLER_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKEREVENTHANDLER_HXX
+
+#include <shobjidl.h>
+
+#include "vistatypes.h"
+#include "IVistaFilePickerInternalNotify.hxx"
+
+#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <osl/interlck.h>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+// types, const etcpp.
+
+
+/** todo document me
+ */
+class VistaFilePickerEventHandler : public ::cppu::BaseMutex
+ , public IFileDialogEvents
+ , public IFileDialogControlEvents
+{
+ public:
+
+
+ // ctor/dtor
+
+
+ explicit VistaFilePickerEventHandler(IVistaFilePickerInternalNotify* pInternalNotify);
+ virtual ~VistaFilePickerEventHandler();
+
+
+ // IUnknown
+
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID rIID ,
+ void** ppObject) override;
+ virtual ULONG STDMETHODCALLTYPE AddRef() override;
+ virtual ULONG STDMETHODCALLTYPE Release() override;
+
+
+ // IFileDialogEvents
+
+
+ STDMETHODIMP OnFileOk(IFileDialog* pDialog) override;
+
+ STDMETHODIMP OnFolderChanging(IFileDialog* pDialog,
+ IShellItem* pFolder) override;
+
+ STDMETHODIMP OnFolderChange(IFileDialog* pDialog) override;
+
+ STDMETHODIMP OnSelectionChange(IFileDialog* pDialog) override;
+
+ STDMETHODIMP OnShareViolation(IFileDialog* pDialog ,
+ IShellItem* pItem ,
+ FDE_SHAREVIOLATION_RESPONSE* pResponse) override;
+
+ STDMETHODIMP OnTypeChange(IFileDialog* pDialog) override;
+
+ STDMETHODIMP OnOverwrite(IFileDialog* pDialog ,
+ IShellItem* pItem ,
+ FDE_OVERWRITE_RESPONSE* pResponse) override;
+
+
+ // IFileDialogControlEvents
+
+
+ STDMETHODIMP OnItemSelected(IFileDialogCustomize* pCustomize,
+ DWORD nIDCtl ,
+ DWORD nIDItem ) override;
+
+ STDMETHODIMP OnButtonClicked(IFileDialogCustomize* pCustomize,
+ DWORD nIDCtl ) override;
+
+ STDMETHODIMP OnCheckButtonToggled(IFileDialogCustomize* pCustomize,
+ DWORD nIDCtl ,
+ BOOL bChecked ) override;
+
+ STDMETHODIMP OnControlActivating(IFileDialogCustomize* pCustomize,
+ DWORD nIDCtl ) override;
+
+
+ // XFilePickerNotifier
+
+ /// @throws css::uno::RuntimeException
+ virtual void addFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener );
+
+ /// @throws css::uno::RuntimeException
+ virtual void removeFilePickerListener( const css::uno::Reference< css::ui::dialogs::XFilePickerListener >& xListener );
+
+
+ // native interface
+
+
+ /** start listening for file picker events on the given file open dialog COM object.
+ *
+ * The broadcaster will be cached internally so deregistration will be easy.
+ * Further all needed information is capsulated within this class (e.g. the listener handler).
+ * Nobody outside must know such information.
+ *
+ * Nothing will happen if an inconsistent state will be detected
+ * (means: double registration will be ignored).
+ *
+ * @param pBroadcaster
+ * reference to the dialog, where we should start listening.
+ */
+ void startListening( const TFileDialog& pBroadcaster );
+
+
+ /** stop listening for file picker events on the internally cached dialog COM object.
+ *
+ * The COM dialog provided on the startListening() call was cached internally.
+ * And now it's used to deregister this listener. Doing so the also internally cached
+ * listener handle is used. If listener was not already registered - nothing will happen.
+ */
+ void stopListening();
+
+ public:
+
+ enum EEventType
+ {
+ E_FILE_SELECTION_CHANGED,
+ E_DIRECTORY_CHANGED,
+ E_HELP_REQUESTED,
+ E_CONTROL_STATE_CHANGED,
+ E_DIALOG_SIZE_CHANGED
+ };
+
+ private:
+
+
+ /// @todo document me
+ void impl_sendEvent( EEventType eEventType,
+ ::sal_Int16 nControlID);
+
+ private:
+
+
+ /// ref count for AddRef/Release()
+ oslInterlockedCount m_nRefCount;
+
+
+ /// unique handle for this listener provided by the broadcaster on registration time
+ DWORD m_nListenerHandle;
+
+
+ /// cached file dialog instance (there we listen for events)
+ TFileDialog m_pDialog;
+
+
+ IVistaFilePickerInternalNotify* m_pInternalNotify;
+
+
+ /** used to inform file picker listener asynchronously.
+ * Those listener must be called asynchronously .. because
+ * every request will block the caller thread. Mostly that will be
+ * the main thread of the office. Further the global SolarMutex will
+ * be locked during this time. If we call our listener back now synchronously ..
+ * we will block on SolarMutex.acquire() forever .-))
+ */
+ ::cppu::OMultiTypeInterfaceContainerHelper m_lListener;
+};
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+#endif // INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKEREVENTHANDLER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/VistaFilePickerImpl.cxx b/fpicker/source/win32/VistaFilePickerImpl.cxx
new file mode 100644
index 000000000..c84fe5f3a
--- /dev/null
+++ b/fpicker/source/win32/VistaFilePickerImpl.cxx
@@ -0,0 +1,1333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "VistaFilePickerImpl.hxx"
+
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ControlActions.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/beans/StringPair.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#include <com/sun/star/lang/SystemDependent.hpp>
+#include <comphelper/sequence.hxx>
+#include <fpicker/strings.hrc>
+#include <fpsofficeResMgr.hxx>
+#include <osl/file.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/process.h>
+#include <o3tl/char16_t2wchar_t.hxx>
+#include "WinImplHelper.hxx"
+
+#include <shlguid.h>
+#include <shlobj.h>
+
+static bool is_current_process_window(HWND hwnd)
+{
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ return (pid == GetCurrentProcessId());
+}
+
+static HWND choose_parent_window()
+{
+ HWND hwnd_parent = GetForegroundWindow();
+ if (!is_current_process_window(hwnd_parent))
+ hwnd_parent = GetDesktopWindow();
+ return hwnd_parent;
+}
+
+namespace {
+
+bool createFolderItem(OUString const & url, ComPtr<IShellItem> & folder) {
+ OUString path;
+ if (osl::FileBase::getSystemPathFromFileURL(url, path)
+ != osl::FileBase::E_None)
+ {
+ return false;
+ }
+ HRESULT res = SHCreateItemFromParsingName(
+ o3tl::toW(path.getStr()), nullptr,
+ IID_PPV_ARGS(&folder));
+ return SUCCEEDED(res);
+}
+
+}
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+// types, const etcpp.
+
+
+static const ::sal_Int16 INVALID_CONTROL_ID = -1;
+static const ::sal_Int16 INVALID_CONTROL_ACTION = -1;
+
+// Guids used for IFileDialog::SetClientGuid
+static const GUID CLIENTID_FILEDIALOG_SIMPLE = {0xB8628FD3, 0xA3F5, 0x4845, 0x9B, 0x62, 0xD5, 0x1E, 0xDF, 0x97, 0xC4, 0x83};
+static const GUID CLIENTID_FILEDIALOG_OPTIONS = {0x93ED486F, 0x0D04, 0x4807, 0x8C, 0x44, 0xAC, 0x26, 0xCB, 0x6C, 0x5D, 0x36};
+static const GUID CLIENTID_FILESAVE_PASSWORD = {0xC12D4F4C, 0x4D41, 0x4D4F, 0x97, 0xEF, 0x87, 0xF9, 0x8D, 0xB6, 0x1E, 0xA6};
+static const GUID CLIENTID_FILESAVE_SELECTION = {0x5B2482B3, 0x0358, 0x4E09, 0xAA, 0x64, 0x2B, 0x76, 0xB2, 0xA0, 0xDD, 0xFE};
+static const GUID CLIENTID_FILESAVE_TEMPLATE = {0x9996D877, 0x20D5, 0x424B, 0x9C, 0x2E, 0xD3, 0xB6, 0x31, 0xEC, 0xF7, 0xCE};
+static const GUID CLIENTID_FILEOPEN_LINK_TEMPLATE = {0x32237796, 0x1509, 0x49D1, 0xBB, 0x7E, 0x63, 0xAD, 0x36, 0xAE, 0x86, 0x8C};
+static const GUID CLIENTID_FILEOPEN_LINK_ANCHOR = {0xBE3188CB, 0x399A, 0x45AE, 0x8F, 0x78, 0x75, 0x17, 0xAF, 0x26, 0x81, 0xEA};
+static const GUID CLIENTID_FILEOPEN_PLAY = {0x32CFB147, 0xF5AE, 0x4F90, 0xA1, 0xF1, 0x81, 0x20, 0x72, 0xBB, 0x2F, 0xC5};
+static const GUID CLIENTID_FILEOPEN_LINK = {0x39AC4BAE, 0x7D2D, 0x46BC, 0xBE, 0x2E, 0xF8, 0x8C, 0xB5, 0x65, 0x5E, 0x6A};
+
+
+static OUString lcl_getURLFromShellItem (IShellItem* pItem)
+{
+ LPWSTR pStr = nullptr;
+ OUString sURL;
+ HRESULT hr;
+
+ hr = pItem->GetDisplayName ( SIGDN_FILESYSPATH, &pStr );
+ if (SUCCEEDED(hr))
+ {
+ ::osl::FileBase::getFileURLFromSystemPath( o3tl::toU(pStr), sURL );
+ goto cleanup;
+ }
+
+ hr = pItem->GetDisplayName ( SIGDN_URL, &pStr );
+ if (SUCCEEDED(hr))
+ {
+ sURL = o3tl::toU(pStr);
+ goto cleanup;
+ }
+
+ hr = pItem->GetDisplayName ( SIGDN_PARENTRELATIVEPARSING, &pStr );
+ if (SUCCEEDED(hr))
+ {
+ GUID known_folder_id;
+ std::wstring aStr = pStr;
+ CoTaskMemFree (pStr);
+
+ if (0 == aStr.compare(0, 3, L"::{"))
+ aStr = aStr.substr(2);
+ hr = IIDFromString(aStr.c_str(), &known_folder_id);
+ if (SUCCEEDED(hr))
+ {
+ hr = SHGetKnownFolderPath(known_folder_id, 0, nullptr, &pStr);
+ if (SUCCEEDED(hr))
+ {
+ ::osl::FileBase::getFileURLFromSystemPath(o3tl::toU(pStr), sURL);
+ goto cleanup;
+ }
+ }
+ }
+
+ // Default fallback
+ hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, nullptr, &pStr);
+ if (SUCCEEDED(hr))
+ ::osl::FileBase::getFileURLFromSystemPath(o3tl::toU(pStr), sURL);
+ else // shouldn't happen...
+ goto bailout;
+
+cleanup:
+ CoTaskMemFree (pStr);
+bailout:
+ return sURL;
+}
+
+// Vista file picker shows the filter mask next to filter name in the list; so we need to remove the
+// mask from the filter name to avoid duplicating masks
+static OUString lcl_AdjustFilterName(const OUString& sName)
+{
+ const sal_Int32 idx = sName.indexOf("(.");
+ return (idx > 0) ? sName.copy(0, idx).trim() : sName;
+}
+
+// rvStrings holds the OUStrings, pointers to which data are stored in returned COMDLG_FILTERSPEC
+static ::std::vector<COMDLG_FILTERSPEC> lcl_buildFilterList(CFilterContainer& rContainer,
+ std::vector<OUString>& rvStrings)
+{
+ ::std::vector< COMDLG_FILTERSPEC > lList ;
+ CFilterContainer::FILTER_ENTRY_T aFilter;
+
+ rContainer.beginEnumFilter( );
+ while( rContainer.getNextFilter(aFilter) )
+ {
+ COMDLG_FILTERSPEC aSpec;
+
+ rvStrings.push_back(lcl_AdjustFilterName(aFilter.first)); // to avoid dangling pointer
+ aSpec.pszName = o3tl::toW(rvStrings.back().getStr());
+ aSpec.pszSpec = o3tl::toW(aFilter.second.getStr());
+
+ lList.push_back(aSpec);
+ }
+
+ return lList;
+}
+
+
+VistaFilePickerImpl::VistaFilePickerImpl()
+ : m_iDialogOpen ()
+ , m_iDialogSave ()
+ , m_iFolderPicker()
+ , m_hLastResult ()
+ , m_lFilters ()
+ , m_iEventHandler(new VistaFilePickerEventHandler(this))
+ , m_bInExecute (false)
+ , m_bWasExecuted (false)
+ , m_hParentWindow(choose_parent_window())
+ , m_sDirectory ()
+ , m_sFilename ()
+{
+}
+
+
+VistaFilePickerImpl::~VistaFilePickerImpl()
+{
+}
+
+
+void VistaFilePickerImpl::before()
+{
+ // SYNCHRONIZED->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // TRICKY .-)
+ // osl::Thread class initializes COm already in MTA mode because it's needed
+ // by VCL and UNO so. There is no way to change that from outside...
+ // but we need a STA environment...
+ // So we make it by try-and-error...
+ // If first CoInitializeEx will fail... we uninitialize COM initialize it new .-)
+
+ m_hLastResult = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+ if ( FAILED(m_hLastResult) )
+ {
+ CoUninitialize();
+ m_hLastResult = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+ }
+}
+
+
+void VistaFilePickerImpl::doRequest(const RequestRef& rRequest)
+{
+ try
+ {
+ switch(rRequest->getRequest())
+ {
+ case E_ADD_PICKER_LISTENER :
+ impl_sta_addFilePickerListener(rRequest);
+ break;
+
+ case E_REMOVE_PICKER_LISTENER :
+ impl_sta_removeFilePickerListener(rRequest);
+ break;
+
+ case E_APPEND_FILTER :
+ impl_sta_appendFilter(rRequest);
+ break;
+
+ case E_APPEND_FILTERGROUP :
+ impl_sta_appendFilterGroup(rRequest);
+ break;
+
+ case E_SET_CURRENT_FILTER :
+ impl_sta_setCurrentFilter(rRequest);
+ break;
+
+ case E_GET_CURRENT_FILTER :
+ impl_sta_getCurrentFilter(rRequest);
+ break;
+
+ case E_CREATE_OPEN_DIALOG :
+ impl_sta_CreateOpenDialog(rRequest);
+ break;
+
+ case E_CREATE_SAVE_DIALOG :
+ impl_sta_CreateSaveDialog(rRequest);
+ break;
+
+ case E_CREATE_FOLDER_PICKER:
+ impl_sta_CreateFolderPicker(rRequest);
+ break;
+
+ case E_SET_MULTISELECTION_MODE :
+ impl_sta_SetMultiSelectionMode(rRequest);
+ break;
+
+ case E_SET_TITLE :
+ impl_sta_SetTitle(rRequest);
+ break;
+
+ case E_SET_FILENAME:
+ impl_sta_SetFileName(rRequest);
+ break;
+
+ case E_SET_DIRECTORY :
+ impl_sta_SetDirectory(rRequest);
+ break;
+
+ case E_GET_DIRECTORY :
+ impl_sta_GetDirectory(rRequest);
+ break;
+
+ case E_SET_DEFAULT_NAME :
+ impl_sta_SetDefaultName(rRequest);
+ break;
+
+ case E_GET_SELECTED_FILES :
+ impl_sta_getSelectedFiles(rRequest);
+ break;
+
+ case E_SHOW_DIALOG_MODAL :
+ impl_sta_ShowDialogModal(rRequest);
+ break;
+
+ case E_SET_CONTROL_VALUE :
+ impl_sta_SetControlValue(rRequest);
+ break;
+
+ case E_GET_CONTROL_VALUE :
+ impl_sta_GetControlValue(rRequest);
+ break;
+
+ case E_SET_CONTROL_LABEL :
+ impl_sta_SetControlLabel(rRequest);
+ break;
+
+ case E_GET_CONTROL_LABEL :
+ impl_sta_GetControlLabel(rRequest);
+ break;
+
+ case E_ENABLE_CONTROL :
+ impl_sta_EnableControl(rRequest);
+ break;
+
+ // no default: let the compiler detect changes on enum ERequest !
+ }
+ }
+ catch(...)
+ {}
+}
+
+
+void VistaFilePickerImpl::after()
+{
+ CoUninitialize();
+}
+
+
+void VistaFilePickerImpl::impl_sta_addFilePickerListener(const RequestRef& rRequest)
+{
+ // SYNCHRONIZED outside !
+ const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
+ if ( ! xListener.is())
+ return;
+
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ TFileDialogEvents iHandler = m_iEventHandler;
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
+ if (pHandlerImpl)
+ pHandlerImpl->addFilePickerListener(xListener);
+}
+
+
+void VistaFilePickerImpl::impl_sta_removeFilePickerListener(const RequestRef& rRequest)
+{
+ // SYNCHRONIZED outside !
+ const css::uno::Reference< css::ui::dialogs::XFilePickerListener > xListener = rRequest->getArgumentOrDefault(PROP_PICKER_LISTENER, css::uno::Reference< css::ui::dialogs::XFilePickerListener >());
+ if ( ! xListener.is())
+ return;
+
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ TFileDialogEvents iHandler = m_iEventHandler;
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
+ if (pHandlerImpl)
+ pHandlerImpl->removeFilePickerListener(xListener);
+}
+
+
+void VistaFilePickerImpl::impl_sta_appendFilter(const RequestRef& rRequest)
+{
+ const OUString sTitle = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, OUString());
+ const OUString sFilter = rRequest->getArgumentOrDefault(PROP_FILTER_VALUE, OUString());
+
+ // SYNCHRONIZED->
+ osl::MutexGuard aLock(m_aMutex);
+
+ m_lFilters.addFilter(sTitle, sFilter);
+}
+
+
+void VistaFilePickerImpl::impl_sta_appendFilterGroup(const RequestRef& rRequest)
+{
+ const css::uno::Sequence< css::beans::StringPair > aFilterGroup =
+ rRequest->getArgumentOrDefault(PROP_FILTER_GROUP, css::uno::Sequence< css::beans::StringPair >());
+
+ // SYNCHRONIZED->
+ osl::MutexGuard aLock(m_aMutex);
+
+ if ( m_lFilters.numFilter() > 0 && aFilterGroup.getLength() > 0 )
+ m_lFilters.addFilter( STRING_SEPARATOR, "", true );
+
+ ::sal_Int32 c = aFilterGroup.getLength();
+ ::sal_Int32 i = 0;
+ for (i=0; i<c; ++i)
+ {
+ const css::beans::StringPair& rFilter = aFilterGroup[i];
+ m_lFilters.addFilter(rFilter.First, rFilter.Second);
+ }
+}
+
+
+void VistaFilePickerImpl::impl_sta_setCurrentFilter(const RequestRef& rRequest)
+{
+ const OUString sTitle = rRequest->getArgumentOrDefault(PROP_FILTER_TITLE, OUString());
+
+ // SYNCHRONIZED->
+ osl::MutexGuard aLock(m_aMutex);
+
+ m_lFilters.setCurrentFilter(sTitle);
+}
+
+
+void VistaFilePickerImpl::impl_sta_getCurrentFilter(const RequestRef& rRequest)
+{
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ UINT nIndex = UINT_MAX;
+ HRESULT hResult = iDialog->GetFileTypeIndex(&nIndex);
+ if (
+ ( FAILED(hResult) ) ||
+ ( nIndex == UINT_MAX ) // COM dialog sometimes return S_OK for empty filter lists .-(
+ )
+ return;
+
+ // SYNCHRONIZED->
+ osl::MutexGuard aLock(m_aMutex);
+
+ OUString sTitle;
+ ::sal_Int32 nRealIndex = nIndex-1; // COM dialog base on 1 ... filter container on 0 .-)
+ if (
+ (nRealIndex >= 0 ) &&
+ (m_lFilters.getFilterNameByIndex(nRealIndex, sTitle))
+ )
+ rRequest->setArgument(PROP_FILTER_TITLE, sTitle);
+ else if ( nRealIndex == -1 ) // Dialog not visible yet
+ {
+ sTitle = m_lFilters.getCurrentFilter();
+ rRequest->setArgument(PROP_FILTER_TITLE, sTitle);
+ }
+ // <- SYNCHRONIZED
+}
+
+
+void VistaFilePickerImpl::impl_sta_CreateDialog(const RequestRef& rRequest, PickerDialog eType, DWORD nOrFlags)
+{
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ TFileDialog iDialog;
+
+ switch (eType)
+ {
+ case PickerDialog::FileOpen:
+ m_hLastResult = m_iDialogOpen.create();
+ if (FAILED(m_hLastResult))
+ return;
+ m_iDialogOpen.query(&iDialog);
+ break;
+
+ case PickerDialog::FileSave:
+ m_hLastResult = m_iDialogSave.create();
+ if (FAILED(m_hLastResult))
+ return;
+ m_iDialogSave.query(&iDialog);
+ break;
+
+ case PickerDialog::Folder:
+ m_hLastResult = m_iFolderPicker.create();
+ if (FAILED(m_hLastResult))
+ return;
+ m_iFolderPicker.query(&iDialog);
+ break;
+ }
+
+ TFileDialogEvents iHandler = m_iEventHandler;
+
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ DWORD nFlags = 0;
+ iDialog->GetOptions ( &nFlags );
+
+ nFlags &= ~FOS_FORCESHOWHIDDEN;
+ nFlags |= FOS_PATHMUSTEXIST;
+ nFlags |= FOS_DONTADDTORECENT;
+ nFlags |= nOrFlags;
+
+ iDialog->SetOptions ( nFlags );
+
+ css::uno::Reference<css::awt::XWindow> xWindow = rRequest->getArgumentOrDefault(PROP_PARENT_WINDOW, css::uno::Reference<css::awt::XWindow>());
+ if(xWindow.is())
+ {
+ css::uno::Reference<css::awt::XSystemDependentWindowPeer> xSysDepWin(xWindow,css::uno::UNO_QUERY);
+ if(xSysDepWin.is()) {
+ css::uno::Sequence<sal_Int8> aProcessIdent(16);
+ rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
+ css::uno::Any aAny = xSysDepWin->getWindowHandle(aProcessIdent,css::lang::SystemDependent::SYSTEM_WIN32);
+ sal_Int64 tmp = 0;
+ aAny >>= tmp;
+ if(tmp != 0)
+ m_hParentWindow = reinterpret_cast<HWND>(tmp);
+ }
+ }
+
+ ::sal_Int32 nFeatures = rRequest->getArgumentOrDefault(PROP_FEATURES, ::sal_Int32(0));
+ ::sal_Int32 nTemplate = rRequest->getArgumentOrDefault(PROP_TEMPLATE_DESCR, ::sal_Int32(0));
+ impl_sta_enableFeatures(nFeatures, nTemplate);
+
+ VistaFilePickerEventHandler* pHandlerImpl = static_cast<VistaFilePickerEventHandler*>(iHandler.get());
+ if (pHandlerImpl)
+ pHandlerImpl->startListening(iDialog);
+}
+
+
+void VistaFilePickerImpl::impl_sta_CreateOpenDialog(const RequestRef& rRequest)
+{
+ DWORD nFlags = 0;
+ nFlags |= FOS_FILEMUSTEXIST;
+ nFlags |= FOS_OVERWRITEPROMPT;
+
+ impl_sta_CreateDialog(rRequest, PickerDialog::FileOpen, nFlags);
+}
+
+
+void VistaFilePickerImpl::impl_sta_CreateSaveDialog(const RequestRef& rRequest)
+{
+ DWORD nFlags = 0;
+ nFlags |= FOS_FILEMUSTEXIST;
+ nFlags |= FOS_OVERWRITEPROMPT;
+
+ impl_sta_CreateDialog(rRequest, PickerDialog::FileSave, nFlags);
+}
+
+
+void VistaFilePickerImpl::impl_sta_CreateFolderPicker(const RequestRef& rRequest)
+{
+ DWORD nFlags = 0;
+ nFlags |= FOS_PICKFOLDERS;
+
+ impl_sta_CreateDialog(rRequest, PickerDialog::Folder, nFlags);
+}
+
+
+static const ::sal_Int32 GROUP_VERSION = 1;
+static const ::sal_Int32 GROUP_TEMPLATE = 2;
+static const ::sal_Int32 GROUP_IMAGETEMPLATE = 3;
+static const ::sal_Int32 GROUP_CHECKBOXES = 4;
+static const ::sal_Int32 GROUP_IMAGEANCHOR = 5;
+
+
+static void setLabelToControl(TFileDialogCustomize iCustom, sal_uInt16 nControlId)
+{
+ OUString aLabel = CResourceProvider::getResString(nControlId);
+ aLabel = SOfficeToWindowsLabel(aLabel);
+ iCustom->SetControlLabel(nControlId, o3tl::toW(aLabel.getStr()) );
+}
+
+
+void VistaFilePickerImpl::impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate)
+{
+ GUID aGUID = {};
+ switch (nTemplate)
+ {
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE :
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_PREVIEW :
+ case css::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE :
+ aGUID = CLIENTID_FILEDIALOG_SIMPLE;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION :
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS :
+ aGUID = CLIENTID_FILEDIALOG_OPTIONS;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_PASSWORD :
+ aGUID = CLIENTID_FILESAVE_PASSWORD;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION :
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_SELECTION :
+ aGUID = CLIENTID_FILESAVE_SELECTION;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE :
+ aGUID = CLIENTID_FILESAVE_TEMPLATE;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE :
+ aGUID = CLIENTID_FILEOPEN_LINK_TEMPLATE;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR :
+ aGUID = CLIENTID_FILEOPEN_LINK_ANCHOR;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_PLAY :
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PLAY :
+ aGUID = CLIENTID_FILEOPEN_PLAY;
+ break;
+
+ case css::ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW :
+ aGUID = CLIENTID_FILEOPEN_LINK;
+ break;
+ }
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ iDialog->SetClientGuid ( aGUID );
+
+ TFileDialogCustomize iCustom = impl_getCustomizeInterface();
+
+ if ((nFeatures & FEATURE_VERSION) == FEATURE_VERSION)
+ {
+ iCustom->StartVisualGroup (GROUP_VERSION, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_VERSION).replaceFirst("~","").getStr()));
+ iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION);
+ iCustom->EndVisualGroup ();
+ iCustom->MakeProminent (GROUP_VERSION);
+ }
+
+ if ((nFeatures & FEATURE_TEMPLATE) == FEATURE_TEMPLATE)
+ {
+ iCustom->StartVisualGroup (GROUP_TEMPLATE, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_TEMPLATES).replaceFirst("~","").getStr()));
+ iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE);
+ iCustom->EndVisualGroup ();
+ iCustom->MakeProminent (GROUP_TEMPLATE);
+ }
+
+ if ((nFeatures & FEATURE_IMAGETEMPLATE) == FEATURE_IMAGETEMPLATE)
+ {
+ iCustom->StartVisualGroup (GROUP_IMAGETEMPLATE, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_IMAGE_TEMPLATE).replaceFirst("~","").getStr()));
+ iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE);
+ iCustom->EndVisualGroup ();
+ iCustom->MakeProminent (GROUP_IMAGETEMPLATE);
+ }
+
+ if ((nFeatures & FEATURE_IMAGEANCHOR) == FEATURE_IMAGEANCHOR)
+ {
+ iCustom->StartVisualGroup (GROUP_IMAGEANCHOR, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_IMAGE_ANCHOR).replaceFirst("~","").getStr()));
+ iCustom->AddComboBox (css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR);
+ iCustom->EndVisualGroup ();
+ iCustom->MakeProminent (GROUP_IMAGEANCHOR);
+ }
+
+ iCustom->StartVisualGroup (GROUP_CHECKBOXES, L"");
+
+ sal_uInt16 nControlId(0);
+ if ((nFeatures & FEATURE_AUTOEXTENSION) == FEATURE_AUTOEXTENSION)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION;
+ iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_AUTO_EXTENSION).replaceFirst("~","").getStr()), true);
+ setLabelToControl(iCustom, nControlId);
+ }
+
+ if ((nFeatures & FEATURE_PASSWORD) == FEATURE_PASSWORD)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD;
+ iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_PASSWORD).replaceFirst("~","").getStr()), false);
+ setLabelToControl(iCustom, nControlId);
+ }
+
+ if ((nFeatures & FEATURE_GPGPASSWORD) == FEATURE_GPGPASSWORD)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION;
+ iCustom->AddCheckButton (nControlId, L"GpgPassword", false);
+ setLabelToControl(iCustom, nControlId);
+ }
+
+ if ((nFeatures & FEATURE_READONLY) == FEATURE_READONLY)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY;
+ iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_READONLY).replaceFirst("~","").getStr()), false);
+ setLabelToControl(iCustom, nControlId);
+ }
+
+ if ((nFeatures & FEATURE_FILTEROPTIONS) == FEATURE_FILTEROPTIONS)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS;
+ iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_FILTER_OPTIONS).replaceFirst("~","").getStr()), false);
+ setLabelToControl(iCustom, nControlId);
+ }
+
+ if ((nFeatures & FEATURE_LINK) == FEATURE_LINK)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK;
+ iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_INSERT_AS_LINK).replaceFirst("~","").getStr()), false);
+ setLabelToControl(iCustom, nControlId);
+ }
+
+ if ((nFeatures & FEATURE_SELECTION) == FEATURE_SELECTION)
+ {
+ nControlId = css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION;
+ iCustom->AddCheckButton (nControlId, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_SELECTION).replaceFirst("~","").getStr()), false);
+ setLabelToControl(iCustom, nControlId);
+ }
+
+ /* can be ignored ... new COM dialog supports preview native now !
+ if ((nFeatures & FEATURE_PREVIEW) == FEATURE_PREVIEW)
+ iCustom->AddCheckButton (css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, L"Preview", false);
+ */
+
+ iCustom->EndVisualGroup();
+
+ if ((nFeatures & FEATURE_PLAY) == FEATURE_PLAY)
+ iCustom->AddPushButton (css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY, o3tl::toW(FpsResId(STR_SVT_FILEPICKER_PLAY).replaceFirst("~","").getStr()));
+
+}
+
+
+void VistaFilePickerImpl::impl_sta_SetMultiSelectionMode(const RequestRef& rRequest)
+{
+ const bool bMultiSelection = rRequest->getArgumentOrDefault(PROP_MULTISELECTION_MODE, true);
+
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ DWORD nFlags = 0;
+ m_hLastResult = iDialog->GetOptions ( &nFlags );
+
+ if (bMultiSelection)
+ nFlags |= FOS_ALLOWMULTISELECT;
+ else
+ nFlags &= ~FOS_ALLOWMULTISELECT;
+
+ iDialog->SetOptions ( nFlags );
+}
+
+
+void VistaFilePickerImpl::impl_sta_SetTitle(const RequestRef& rRequest)
+{
+ OUString sTitle = rRequest->getArgumentOrDefault(PROP_TITLE, OUString());
+
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ iDialog->SetTitle(o3tl::toW(sTitle.getStr()));
+}
+
+
+void VistaFilePickerImpl::impl_sta_SetFileName(const RequestRef& rRequest)
+{
+ OUString sFileName = rRequest->getArgumentOrDefault(PROP_FILENAME, OUString());
+
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ iDialog->SetFileName(o3tl::toW(sFileName.getStr()));
+}
+
+
+void VistaFilePickerImpl::impl_sta_SetDirectory(const RequestRef& rRequest)
+{
+ OUString sDirectory = rRequest->getArgumentOrDefault(PROP_DIRECTORY, OUString());
+
+ if( !m_bInExecute)
+ {
+ // Vista stores last used folders for file dialogs
+ // so we don't want the application to change the folder
+ // in most cases.
+ // Store the requested folder in the meantime and decide later
+ // what to do
+ m_sDirectory = sDirectory;
+ }
+
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ ComPtr< IShellItem > pFolder;
+ if ( !createFolderItem(sDirectory, pFolder) )
+ return;
+
+ iDialog->SetFolder(pFolder);
+}
+
+OUString VistaFilePickerImpl::GetDirectory()
+{
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ ComPtr< IShellItem > pFolder;
+ HRESULT hResult = iDialog->GetFolder( &pFolder );
+ if ( FAILED(hResult) )
+ return OUString();
+ return lcl_getURLFromShellItem(pFolder);
+}
+
+void VistaFilePickerImpl::impl_sta_GetDirectory(const RequestRef& rRequest)
+{
+ const OUString sFolder = m_sDirectory.isEmpty() ? GetDirectory() : m_sDirectory;
+ if (!sFolder.isEmpty())
+ rRequest->setArgument(PROP_DIRECTORY, sFolder);
+}
+
+void VistaFilePickerImpl::impl_sta_SetDefaultName(const RequestRef& rRequest)
+{
+ OUString sFilename = rRequest->getArgumentOrDefault(PROP_FILENAME, OUString());
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+
+ TFileDialogCustomize iCustom = impl_getCustomizeInterface();
+ if ( ! iCustom.is())
+ return;
+
+ // if we have the autoextension check box set, remove (or change ???) the extension of the filename
+ // so that the autoextension mechanism can do its job
+ BOOL bValue = FALSE;
+ HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
+ if ( FAILED(hResult) )
+ return;
+ if ( bValue )
+ {
+ sal_Int32 nSepPos = sFilename.lastIndexOf( '.' );
+ if ( -1 != nSepPos )
+ sFilename = sFilename.copy(0, nSepPos);
+ }
+
+ iDialog->SetFileName (o3tl::toW(sFilename.getStr()));
+ m_sFilename = sFilename;
+}
+
+
+void VistaFilePickerImpl::impl_sta_setFiltersOnDialog()
+{
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ std::vector<OUString> vStrings; // to hold the adjusted filter names, pointers to which will be
+ // stored in lFilters
+ ::std::vector< COMDLG_FILTERSPEC > lFilters = lcl_buildFilterList(m_lFilters, vStrings);
+ OUString sCurrentFilter = m_lFilters.getCurrentFilter();
+ sal_Int32 nCurrentFilter = m_lFilters.getFilterPos(sCurrentFilter);
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ TFileDialogCustomize iCustomize = impl_getCustomizeInterface();
+
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ if (lFilters.empty())
+ return;
+
+ COMDLG_FILTERSPEC *pFilt = lFilters.data();
+ iDialog->SetFileTypes(lFilters.size(), pFilt/*&lFilters[0]*/);
+ iDialog->SetFileTypeIndex(nCurrentFilter + 1);
+
+ BOOL bValue = FALSE;
+ HRESULT hResult = iCustomize->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
+ if ( FAILED(hResult) )
+ return;
+
+ if ( bValue )
+ {
+ PCWSTR lpFilterExt = lFilters[0].pszSpec;
+
+ lpFilterExt = wcsrchr( lpFilterExt, '.' );
+ if ( lpFilterExt )
+ lpFilterExt++;
+ iDialog->SetDefaultExtension( lpFilterExt );
+ }
+
+}
+
+
+void VistaFilePickerImpl::impl_sta_getSelectedFiles(const RequestRef& rRequest)
+{
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ TFileOpenDialog iOpen = m_iDialogOpen;
+ TFileSaveDialog iSave = m_iDialogSave;
+ TFolderPickerDialog iPick = m_iFolderPicker;
+ bool bInExecute = m_bInExecute;
+
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ // ask dialog for results
+ // Note : we must differ between single/multi selection !
+ // Note further: we must react different if dialog is in execute or not .-(
+ ComPtr< IShellItem > iItem;
+ ComPtr< IShellItemArray > iItems;
+ HRESULT hResult = E_FAIL;
+
+ if (iOpen.is())
+ {
+ if (bInExecute)
+ hResult = iOpen->GetSelectedItems(&iItems);
+ else
+ {
+ hResult = iOpen->GetResults(&iItems);
+ if (FAILED(hResult))
+ hResult = iOpen->GetResult(&iItem);
+ }
+ }
+ else if (iSave.is())
+ {
+ if (bInExecute)
+ hResult = iSave->GetCurrentSelection(&iItem);
+ else
+ hResult = iSave->GetResult(&iItem);
+ }
+ else if (iPick.is())
+ {
+ if (bInExecute)
+ hResult = iPick->GetCurrentSelection(&iItem);
+ else
+ {
+ hResult = iPick->GetResult(&iItem);
+ }
+ }
+
+ if (FAILED(hResult))
+ return;
+
+ // convert and pack results
+ std::vector< OUString > lFiles;
+ if (iItem.is())
+ {
+ const OUString sURL = lcl_getURLFromShellItem(iItem);
+ if (sURL.getLength() > 0)
+ lFiles.push_back(sURL);
+ }
+
+ if (iItems.is())
+ {
+ DWORD nCount;
+ hResult = iItems->GetCount(&nCount);
+ if ( SUCCEEDED(hResult) )
+ {
+ for (DWORD i=0; i<nCount; ++i)
+ {
+ hResult = iItems->GetItemAt(i, &iItem);
+ if ( SUCCEEDED(hResult) )
+ {
+ const OUString sURL = lcl_getURLFromShellItem(iItem);
+ if (sURL.getLength() > 0)
+ lFiles.push_back(sURL);
+ }
+ }
+ }
+ }
+
+ rRequest->setArgument(PROP_SELECTED_FILES, comphelper::containerToSequence(lFiles));
+}
+
+
+void VistaFilePickerImpl::impl_sta_ShowDialogModal(const RequestRef& rRequest)
+{
+ impl_sta_setFiltersOnDialog();
+
+ // SYNCHRONIZED->
+ ::osl::ResettableMutexGuard aLock(m_aMutex);
+
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ TFileOpenDialog iOpen = m_iDialogOpen;
+ TFileSaveDialog iSave = m_iDialogSave;
+ TFolderPickerDialog iPick = m_iFolderPicker;
+
+ // it's important to know if we are showing the dialog.
+ // Some dialog interface methods can't be called then or some
+ // tasks must be done differently .-) (e.g. see impl_sta_getSelectedFiles())
+ m_bInExecute = true;
+
+ m_bWasExecuted = true;
+
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ // we set the directory only if we have a save dialog and a filename
+ // for the other cases, the file dialog remembers its last location
+ // according to its client guid.
+ if( m_sDirectory.getLength())
+ {
+ ComPtr< IShellItem > pFolder;
+ if ( createFolderItem(m_sDirectory, pFolder) )
+ {
+ if (m_sFilename.getLength())
+ {
+ OUString aFileURL(m_sDirectory);
+ sal_Int32 nIndex = aFileURL.lastIndexOf('/');
+ if (nIndex != aFileURL.getLength()-1)
+ aFileURL += "/";
+ aFileURL += m_sFilename;
+
+ TFileDialogCustomize iCustom = impl_getCustomizeInterface();
+
+ BOOL bValue = FALSE;
+ HRESULT hResult = iCustom->GetCheckButtonState( css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &bValue);
+ if ( bValue )
+ {
+ UINT nFileType;
+ hResult = iDialog->GetFileTypeIndex(&nFileType);
+ if ( SUCCEEDED(hResult) && nFileType > 0 )
+ {
+ // COM dialog base on 1 ... filter container on 0 .-)
+ ::size_t nRealIndex = nFileType-1;
+ OUString sFilter;
+ if (m_lFilters.getFilterByIndex(nRealIndex, sFilter))
+ {
+ const sal_Int32 idx = sFilter.indexOf('.');
+ if (idx >= 0)
+ aFileURL += sFilter.copy(idx);
+ }
+ }
+ }
+
+ // Check existence of file. Set folder only for this special case
+ OUString aSystemPath;
+ osl_getSystemPathFromFileURL( aFileURL.pData, &aSystemPath.pData );
+
+ WIN32_FIND_DATAW aFindFileData;
+ HANDLE hFind = FindFirstFileW( o3tl::toW(aSystemPath.getStr()), &aFindFileData );
+ if (hFind != INVALID_HANDLE_VALUE)
+ iDialog->SetFolder(pFolder);
+ else
+ hResult = iDialog->AddPlace(pFolder, FDAP_TOP);
+
+ FindClose( hFind );
+ }
+ else
+ iDialog->AddPlace(pFolder, FDAP_TOP);
+ }
+ }
+
+
+ HRESULT hResult = E_FAIL;
+ try
+ {
+ // show dialog and wait for user decision
+ if (iOpen.is())
+ hResult = iOpen->Show( m_hParentWindow ); // parent window needed
+ else
+ if (iSave.is())
+ hResult = iSave->Show( m_hParentWindow ); // parent window needed
+ else
+ if (iPick.is())
+ hResult = iPick->Show( m_hParentWindow ); // parent window needed
+ }
+ catch(...)
+ {}
+
+ // SYNCHRONIZED->
+ aLock.reset();
+ m_bInExecute = false;
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ if ( FAILED(hResult) )
+ return;
+
+ impl_sta_getSelectedFiles(rRequest);
+ rRequest->setArgument(PROP_DIALOG_SHOW_RESULT, true);
+}
+
+
+TFileDialog VistaFilePickerImpl::impl_getBaseDialogInterface()
+{
+ TFileDialog iDialog;
+
+ // SYNCHRONIZED->
+ osl::MutexGuard aLock(m_aMutex);
+
+ if (m_iDialogOpen.is())
+ m_iDialogOpen.query(&iDialog);
+ if (m_iDialogSave.is())
+ m_iDialogSave.query(&iDialog);
+ if (m_iFolderPicker.is())
+ m_iFolderPicker.query(&iDialog);
+
+ return iDialog;
+}
+
+
+TFileDialogCustomize VistaFilePickerImpl::impl_getCustomizeInterface()
+{
+ TFileDialogCustomize iCustom;
+
+ // SYNCHRONIZED->
+ osl::MutexGuard aLock(m_aMutex);
+
+ if (m_iDialogOpen.is())
+ m_iDialogOpen.query(&iCustom);
+ else if (m_iDialogSave.is())
+ m_iDialogSave.query(&iCustom);
+ else if (m_iFolderPicker.is())
+ m_iFolderPicker.query(&iCustom);
+
+ return iCustom;
+}
+
+
+static void lcl_removeControlItemsWorkaround(const TFileDialogCustomize& iCustom ,
+ ::sal_Int16 nControlId)
+{
+ (void)iCustom->SetSelectedControlItem(nControlId, 1000); // Don't care if this fails (useless?)
+ DWORD i = 0;
+ HRESULT hResult = S_OK;
+ while ( SUCCEEDED(hResult) )
+ hResult = iCustom->RemoveControlItem(nControlId, i++);
+}
+
+
+void VistaFilePickerImpl::impl_sta_SetControlValue(const RequestRef& rRequest)
+{
+ ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID );
+ ::sal_Int16 nAction = rRequest->getArgumentOrDefault(PROP_CONTROL_ACTION, INVALID_CONTROL_ACTION);
+ css::uno::Any aValue = rRequest->getValue(PROP_CONTROL_VALUE);
+
+ // don't check for right values here ...
+ // most parameters are optional !
+
+ TFileDialogCustomize iCustom = impl_getCustomizeInterface();
+ if ( ! iCustom.is())
+ return;
+
+ switch (nId)
+ {
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
+ //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
+ {
+ bool bValue = false;
+ aValue >>= bValue;
+ iCustom->SetCheckButtonState(nId, bValue);
+ }
+ break;
+
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR :
+ {
+ HRESULT hResult;
+ switch (nAction)
+ {
+ case css::ui::dialogs::ControlActions::DELETE_ITEMS :
+ {
+ hResult = iCustom->RemoveAllControlItems(nId);
+ if ( FAILED(hResult) )
+ lcl_removeControlItemsWorkaround(iCustom, nId);
+ }
+ break;
+
+ case css::ui::dialogs::ControlActions::ADD_ITEMS :
+ {
+ aValue >>= m_lItems;
+ for (::sal_Int32 i=0; i<m_lItems.getLength(); ++i)
+ {
+ const OUString& sItem = m_lItems[i];
+ hResult = iCustom->AddControlItem(nId, i, o3tl::toW(sItem.getStr()));
+ }
+ }
+ break;
+
+ case css::ui::dialogs::ControlActions::SET_SELECT_ITEM :
+ {
+ ::sal_Int32 nItem = 0;
+ aValue >>= nItem;
+ hResult = iCustom->SetSelectedControlItem(nId, nItem);
+ }
+ break;
+ }
+ }
+ break;
+
+ case css::ui::dialogs::ExtendedFilePickerElementIds::PUSHBUTTON_PLAY :
+ {
+ }
+ break;
+ }
+}
+
+
+void VistaFilePickerImpl::impl_sta_GetControlValue(const RequestRef& rRequest)
+{
+ ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID );
+
+ // don't check for right values here ...
+ // most parameters are optional !
+
+ TFileDialogCustomize iCustom = impl_getCustomizeInterface();
+ if ( ! iCustom.is())
+ return;
+
+ css::uno::Any aValue;
+ if( m_bWasExecuted )
+ switch (nId)
+ {
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PASSWORD :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_GPGENCRYPTION :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_READONLY :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS :
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_LINK :
+ //case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_PREVIEW : // can be ignored ... preview is supported native now !
+ case css::ui::dialogs::ExtendedFilePickerElementIds::CHECKBOX_SELECTION :
+ {
+ BOOL bValue = FALSE;
+ HRESULT hResult = iCustom->GetCheckButtonState(nId, &bValue);
+ if ( SUCCEEDED(hResult) )
+ aValue <<= bool(bValue);
+ }
+ break;
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_VERSION:
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_TEMPLATE:
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE:
+ case css::ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR:
+ {
+ DWORD bValue = 0;
+ HRESULT hResult = iCustom->GetSelectedControlItem(nId, &bValue);
+ if ( SUCCEEDED(hResult) )
+ {
+ const OUString& sItem = m_lItems[bValue];
+ aValue <<= OUString(sItem.getStr());
+ }
+ }
+ break;
+ }
+
+ if (aValue.hasValue())
+ rRequest->setArgument(PROP_CONTROL_VALUE, aValue);
+}
+
+
+void VistaFilePickerImpl::impl_sta_SetControlLabel(const RequestRef& rRequest)
+{
+ ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID );
+ OUString sLabel = rRequest->getArgumentOrDefault(PROP_CONTROL_LABEL, OUString() );
+
+ // don't check for right values here ...
+ // most parameters are optional !
+
+ TFileDialogCustomize iCustom = impl_getCustomizeInterface();
+ if ( ! iCustom.is())
+ return;
+ iCustom->SetControlLabel (nId, o3tl::toW(sLabel.getStr()));
+}
+
+
+void VistaFilePickerImpl::impl_sta_GetControlLabel(const RequestRef& /*rRequest*/)
+{
+}
+
+
+void VistaFilePickerImpl::impl_sta_EnableControl(const RequestRef& rRequest)
+{
+ ::sal_Int16 nId = rRequest->getArgumentOrDefault(PROP_CONTROL_ID , INVALID_CONTROL_ID );
+ bool bEnabled = rRequest->getArgumentOrDefault(PROP_CONTROL_ENABLE, true);
+
+ // don't check for right values here ...
+ // most parameters are optional !
+
+ TFileDialogCustomize iCustom = impl_getCustomizeInterface();
+ if ( ! iCustom.is())
+ return;
+
+ CDCONTROLSTATEF eState = CDCS_VISIBLE;
+ if (bEnabled)
+ eState |= CDCS_ENABLED;
+ else
+ eState |= CDCS_INACTIVE;
+
+ iCustom->SetControlState(nId, eState);
+}
+
+void VistaFilePickerImpl::impl_SetDefaultExtension( const OUString& currentFilter )
+{
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+ if (currentFilter.getLength())
+ {
+ OUString FilterExt;
+ m_lFilters.getFilterByName(currentFilter, FilterExt);
+
+ sal_Int32 posOfPoint = FilterExt.indexOf(L'.');
+ const sal_Unicode* pFirstExtStart = FilterExt.getStr() + posOfPoint + 1;
+
+ sal_Int32 posOfSemiColon = FilterExt.indexOf(L';') - 1;
+ if (posOfSemiColon < 0)
+ posOfSemiColon = FilterExt.getLength() - 1;
+
+ FilterExt = OUString(pFirstExtStart, posOfSemiColon - posOfPoint);
+ iDialog->SetDefaultExtension ( o3tl::toW(FilterExt.getStr()) );
+ }
+}
+
+void VistaFilePickerImpl::onAutoExtensionChanged (bool bChecked)
+{
+ // SYNCHRONIZED->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ const OUString sFilter = m_lFilters.getCurrentFilter ();
+ OUString sExt ;
+ if (!m_lFilters.getFilterByName(sFilter, sExt))
+ return;
+
+ TFileDialog iDialog = impl_getBaseDialogInterface();
+
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ PCWSTR pExt = nullptr;
+ if ( bChecked )
+ {
+ pExt = o3tl::toW(sExt.getStr());
+ pExt = wcsrchr( pExt, '.' );
+ if ( pExt )
+ pExt++;
+ }
+ iDialog->SetDefaultExtension( pExt );
+}
+
+bool VistaFilePickerImpl::onFileTypeChanged( UINT /*nTypeIndex*/ )
+{
+ return true;
+}
+
+void VistaFilePickerImpl::onDirectoryChanged()
+{
+ m_sDirectory = GetDirectory();
+}
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/VistaFilePickerImpl.hxx b/fpicker/source/win32/VistaFilePickerImpl.hxx
new file mode 100644
index 000000000..e5d2d88e4
--- /dev/null
+++ b/fpicker/source/win32/VistaFilePickerImpl.hxx
@@ -0,0 +1,337 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKERIMPL_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKERIMPL_HXX
+
+#include "platform_vista.h"
+
+#include <shobjidl.h>
+
+#include "asyncrequests.hxx"
+#include "comptr.hxx"
+#include "vistatypes.h"
+#include "FilterContainer.hxx"
+#include "VistaFilePickerEventHandler.hxx"
+#include "IVistaFilePickerInternalNotify.hxx"
+#include "resourceprovider.hxx"
+
+#include <cppuhelper/interfacecontainer.h>
+#include <cppuhelper/basemutex.hxx>
+#include <osl/thread.hxx>
+#include <osl/conditn.hxx>
+#include <rtl/ustring.hxx>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+// types, const etcpp
+
+
+static const ::sal_Int32 FEATURE_AUTOEXTENSION = 1;
+static const ::sal_Int32 FEATURE_PASSWORD = 2;
+static const ::sal_Int32 FEATURE_FILTEROPTIONS = 4;
+static const ::sal_Int32 FEATURE_SELECTION = 8;
+static const ::sal_Int32 FEATURE_TEMPLATE = 16;
+static const ::sal_Int32 FEATURE_LINK = 32;
+static const ::sal_Int32 FEATURE_PREVIEW = 64;
+static const ::sal_Int32 FEATURE_IMAGETEMPLATE = 128;
+static const ::sal_Int32 FEATURE_PLAY = 256;
+static const ::sal_Int32 FEATURE_READONLY = 512;
+static const ::sal_Int32 FEATURE_VERSION = 1024;
+static const ::sal_Int32 FEATURE_GPGPASSWORD = 2048;
+static const ::sal_Int32 FEATURE_IMAGEANCHOR = 4096;
+
+static const OUString PROP_PICKER_LISTENER("picker_listener" ); // [XFilePickerListenert]
+static const OUString PROP_DIALOG_SHOW_RESULT("dialog_show_result" ); // [sal_Bool] true=OK, false=CANCEL
+static const OUString PROP_SELECTED_FILES("selected_files" ); // [seq< OUString >] contains all user selected files (can be empty!)
+static const OUString PROP_MULTISELECTION_MODE("multiselection_mode"); // [sal_Bool] true=ON, false=OFF
+static const OUString PROP_TITLE("title" ); // [OUString]
+static const OUString PROP_FILENAME("filename" ); // [OUString]
+static const OUString PROP_DIRECTORY("directory" ); // [OUString]
+static const OUString PROP_FEATURES("features" ); // [sal_Int32]
+static const OUString PROP_TEMPLATE_DESCR("templatedescription"); // [sal_Int32]
+static const OUString PROP_FILTER_TITLE("filter_title" ); // [OUString]
+static const OUString PROP_FILTER_VALUE("filter_value" ); // [OUString]
+static const OUString PROP_FILTER_GROUP("filter-group" ); // [seq< css:beans::StringPair >] contains a group of filters
+
+static const OUString PROP_CONTROL_ID("control_id" ); // [sal_Int16]
+static const OUString PROP_CONTROL_ACTION("control_action" ); // [sal_Int16]
+static const OUString PROP_CONTROL_VALUE("control_value" ); // [Any]
+static const OUString PROP_CONTROL_LABEL("control_label" ); // [OUString]
+static const OUString PROP_CONTROL_ENABLE("control_enable" ); // [sal_Bool] true=ON, false=OFF
+static const OUString PROP_PARENT_WINDOW("ParentWindow"); //[css::awt::XWindow] preferred parent window
+static const OUString STRING_SEPARATOR("------------------------------------------" );
+
+
+/** native implementation of the file picker on Vista and upcoming windows versions.
+ * This dialog uses COM internally. Further it marshall every request so it will
+ * be executed within its own STA thread !
+ */
+
+class VistaFilePickerImpl : private ::cppu::BaseMutex
+ , public RequestHandler
+ , public IVistaFilePickerInternalNotify
+{
+ public:
+
+ // Workaround made to get input in Template Listbox
+ css::uno::Sequence< OUString > m_lItems;
+ /** used for marshalling requests.
+ * Will be used to map requests to the right implementations.
+ */
+ enum ERequest
+ {
+ E_NO_REQUEST,
+ E_ADD_PICKER_LISTENER,
+ E_REMOVE_PICKER_LISTENER,
+ E_APPEND_FILTER,
+ E_SET_CURRENT_FILTER,
+ E_GET_CURRENT_FILTER,
+ E_CREATE_OPEN_DIALOG,
+ E_CREATE_SAVE_DIALOG,
+ E_CREATE_FOLDER_PICKER,
+ E_SET_MULTISELECTION_MODE,
+ E_SET_TITLE,
+ E_SET_FILENAME,
+ E_GET_DIRECTORY,
+ E_SET_DIRECTORY,
+ E_SET_DEFAULT_NAME,
+ E_GET_SELECTED_FILES,
+ E_SHOW_DIALOG_MODAL,
+ E_SET_CONTROL_VALUE,
+ E_GET_CONTROL_VALUE,
+ E_SET_CONTROL_LABEL,
+ E_GET_CONTROL_LABEL,
+ E_ENABLE_CONTROL,
+ E_APPEND_FILTERGROUP
+ };
+
+ public:
+
+
+ // ctor/dtor - nothing special
+
+ VistaFilePickerImpl();
+ virtual ~VistaFilePickerImpl() override;
+
+
+ // RequestHandler
+
+
+ virtual void before() override;
+ virtual void doRequest(const RequestRef& rRequest) override;
+ virtual void after() override;
+
+
+ // IVistaFilePickerInternalNotify
+
+ virtual void onAutoExtensionChanged (bool bChecked) override;
+ virtual bool onFileTypeChanged( UINT nTypeIndex ) override;
+ virtual void onDirectoryChanged() override;
+
+ private:
+ OUString GetDirectory();
+
+ /// implementation of request E_ADD_FILEPICKER_LISTENER
+ void impl_sta_addFilePickerListener(const RequestRef& rRequest);
+
+
+ /// implementation of request E_REMOVE_FILEPICKER_LISTENER
+ void impl_sta_removeFilePickerListener(const RequestRef& rRequest);
+
+
+ /// implementation of request E_APPEND_FILTER
+ void impl_sta_appendFilter(const RequestRef& rRequest);
+
+
+ /// implementation of request E_APPEND_FILTERGROUP
+ void impl_sta_appendFilterGroup(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_CURRENT_FILTER
+ void impl_sta_setCurrentFilter(const RequestRef& rRequest);
+
+
+ /// implementation of request E_GET_CURRENT_FILTER
+ void impl_sta_getCurrentFilter(const RequestRef& rRequest);
+
+
+ /// implementation of request E_CREATE_OPEN_DIALOG
+ void impl_sta_CreateOpenDialog(const RequestRef& rRequest);
+
+
+ /// implementation of request E_CREATE_SAVE_DIALOG
+ void impl_sta_CreateSaveDialog(const RequestRef& rRequest);
+
+
+ /// implementation of request E_CREATE_FOLDER_PICKER
+ void impl_sta_CreateFolderPicker(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_MULTISELECTION_MODE
+ void impl_sta_SetMultiSelectionMode(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_TITLE
+ void impl_sta_SetTitle(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_FILENAME
+ void impl_sta_SetFileName(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_DIRECTORY
+ void impl_sta_SetDirectory(const RequestRef& rRequest);
+
+
+ /// implementation of request E_GET_DIRECTORY
+ void impl_sta_GetDirectory(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_DEFAULT_NAME
+ void impl_sta_SetDefaultName(const RequestRef& rRequest);
+
+
+ /// implementation of request E_GET_SELECTED_FILES
+ void impl_sta_getSelectedFiles(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SHOW_DIALOG_MODAL
+ void impl_sta_ShowDialogModal(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_CONTROL_VALUE
+ void impl_sta_SetControlValue(const RequestRef& rRequest);
+
+
+ /// implementation of request E_GET_CONTROL_VALUE
+ void impl_sta_GetControlValue(const RequestRef& rRequest);
+
+
+ /// implementation of request E_SET_CONTROL_LABEL
+ void impl_sta_SetControlLabel(const RequestRef& rRequest);
+
+
+ /// implementation of request E_GET_CONTROL_LABEL
+ static void impl_sta_GetControlLabel(const RequestRef& rRequest);
+
+
+ /// implementation of request E_ENABLE_CONTROL
+ void impl_sta_EnableControl(const RequestRef& rRequest);
+
+ /** create all needed (optional!) UI controls addressed by the field nFeatures.
+ * The given number nFeatures is used as a flag field. Use const values FEATURE_XXX
+ * to address it.
+ *
+ * Internal new controls will be added to the dialog. Every control can be accessed
+ * by its own control id. Those control ID must be one of the const set
+ * css::ui::dialogs::ExtendedFilePickerElementIds.
+ *
+ * @see setControlValue()
+ * @see getControlValue()
+ * @see setControlLabel()
+ * @see getControlLabel()
+ * @see enableControl()
+ *
+ * @param nFeatures
+ * flag field(!) knows all features which must be enabled.
+ */
+ void impl_sta_enableFeatures(::sal_Int32 nFeatures, ::sal_Int32 nTemplate);
+
+
+ /** returns an interface, which can be used to customize the internally used
+ * COM dialog.
+ *
+ * Because we use two member (open/save dialog) internally, this method
+ * ask the current active one for its customization interface.
+ *
+ * @return the customization interface for the current used dialog.
+ * Must not be null.
+ */
+ TFileDialogCustomize impl_getCustomizeInterface();
+ TFileDialog impl_getBaseDialogInterface();
+
+
+ /// fill filter list of internal used dialog.
+ void impl_sta_setFiltersOnDialog();
+
+ void impl_SetDefaultExtension( const OUString& currentFilter );
+
+ private:
+ enum class PickerDialog
+ {
+ FileOpen,
+ FileSave,
+ Folder,
+ };
+
+ void impl_sta_CreateDialog(const RequestRef& rRequest, PickerDialog eType, DWORD nOrFlags);
+
+
+ /// COM object representing a file open dialog
+ TFileOpenDialog m_iDialogOpen;
+
+
+ /// COM object representing a file save dialog
+ TFileSaveDialog m_iDialogSave;
+
+
+ /// COM object representing a folder picker dialog
+ TFolderPickerDialog m_iFolderPicker;
+
+
+ /// knows the return state of the last COM call
+ HRESULT m_hLastResult;
+
+
+ /// @todo document me
+ CFilterContainer m_lFilters;
+
+
+ /** help us to handle dialog events and provide them to interested office
+ * listener.
+ */
+ TFileDialogEvents m_iEventHandler;
+
+
+ /// @todo document me
+ bool m_bInExecute;
+
+ bool m_bWasExecuted;
+
+ // handle to parent window
+ HWND m_hParentWindow;
+
+
+ OUString m_sDirectory;
+
+
+ OUString m_sFilename;
+};
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+#endif // INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTAFILEPICKERIMPL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/WinImplHelper.cxx b/fpicker/source/win32/WinImplHelper.cxx
new file mode 100644
index 000000000..ab1dcbe00
--- /dev/null
+++ b/fpicker/source/win32/WinImplHelper.cxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "WinImplHelper.hxx"
+
+#include <vector>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+using ::com::sun::star::lang::IllegalArgumentException;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::XInterface;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Sequence;
+
+const OUString TILDE( "~" );
+const sal_Unicode TILDE_SIGN = L'~';
+const OUString AMPERSAND( "&" );
+const sal_Unicode AMPERSAND_SIGN = L'&';
+
+// OS NAME Platform Major Minor
+
+// Windows NT 3.51 VER_PLATFORM_WIN32_NT 3 51
+// Windows NT 4.0 VER_PLATFORM_WIN32_NT 4 0
+// Windows 2000 VER_PLATFORM_WIN32_NT 5 0
+// Windows XP VER_PLATFORM_WIN32_NT 5 1
+// Windows Vista VER_PLATFORM_WIN32_NT 6 0
+// Windows 7 VER_PLATFORM_WIN32_NT 6 1
+// Windows 95 VER_PLATFORM_WIN32_WINDOWS 4 0
+// Windows 98 VER_PLATFORM_WIN32_WINDOWS 4 10
+// Windows ME VER_PLATFORM_WIN32_WINDOWS 4 90
+
+
+static void Replace( const OUString& aLabel, sal_Unicode OldChar, sal_Unicode NewChar, OUStringBuffer& aBuffer )
+{
+ OSL_ASSERT( aLabel.getLength( ) );
+ OSL_ASSERT( aBuffer.getCapacity( ) >= (aLabel.getLength( )) );
+
+ sal_Int32 i = 0;
+ const sal_Unicode* pCurrent = aLabel.getStr( );
+ const sal_Unicode* pNext = aLabel.getStr( ) + 1;
+ const sal_Unicode* pEnd = aLabel.getStr( ) + aLabel.getLength( );
+
+ while( pCurrent < pEnd )
+ {
+ OSL_ASSERT( pNext <= pEnd );
+ OSL_ASSERT( (i >= 0) && (i < aBuffer.getCapacity( )) );
+
+ if ( OldChar == *pCurrent )
+ {
+ if ( OldChar == *pNext )
+ {
+ // two OldChars in line will
+ // be replaced by one
+ // e.g. ~~ -> ~
+ aBuffer.insert( i, *pCurrent );
+
+ // skip the next one
+ pCurrent++;
+ pNext++;
+ }
+ else
+ {
+ // one OldChar will be replace
+ // by NexChar
+ aBuffer.insert( i, NewChar );
+ }
+ }
+ else if ( *pCurrent == NewChar )
+ {
+ // a NewChar will be replaced by
+ // two NewChars
+ // e.g. & -> &&
+ aBuffer.insert( i++, *pCurrent );
+ aBuffer.insert( i, *pCurrent );
+ }
+ else
+ {
+ aBuffer.insert( i, *pCurrent );
+ }
+
+ pCurrent++;
+ pNext++;
+ i++;
+ }
+}
+
+// converts a soffice label to a windows label
+// the following rules for character replacements
+// will be done:
+// '~' -> '&'
+// '~~' -> '~'
+// '&' -> '&&'
+
+OUString SOfficeToWindowsLabel( const OUString& aSOLabel )
+{
+ OUString aWinLabel = aSOLabel;
+
+ if ( (aWinLabel.indexOf( TILDE ) > -1) || (aWinLabel.indexOf( AMPERSAND ) > -1) )
+ {
+ sal_Int32 nStrLen = aWinLabel.getLength( );
+
+ // in the worst case the new string is
+ // doubled in length, maybe some waste
+ // of memory but how long is a label
+ // normally(?)
+ OUStringBuffer aBuffer( nStrLen * 2 );
+
+ Replace( aWinLabel, TILDE_SIGN, AMPERSAND_SIGN, aBuffer );
+
+ aWinLabel = aBuffer.makeStringAndClear( );
+ }
+
+ return aWinLabel;
+}
+
+// converts a windows label to a soffice label
+// the following rules for character replacements
+// will be done:
+// '&' -> '~'
+// '&&' -> '&'
+// '~' -> '~~'
+
+OUString WindowsToSOfficeLabel( const OUString& aWinLabel )
+{
+ OUString aSOLabel = aWinLabel;
+
+ if ( (aSOLabel.indexOf( TILDE ) > -1) || (aSOLabel.indexOf( AMPERSAND ) > -1) )
+ {
+ sal_Int32 nStrLen = aSOLabel.getLength( );
+
+ // in the worst case the new string is
+ // doubled in length, maybe some waste
+ // of memory but how long is a label
+ // normally(?)
+ OUStringBuffer aBuffer( nStrLen * 2 );
+
+ Replace( aSOLabel, AMPERSAND_SIGN, TILDE_SIGN, aBuffer );
+
+ aSOLabel = aBuffer.makeStringAndClear( );
+ }
+
+ return aSOLabel;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/WinImplHelper.hxx b/fpicker/source/win32/WinImplHelper.hxx
new file mode 100644
index 000000000..acac133d3
--- /dev/null
+++ b/fpicker/source/win32/WinImplHelper.hxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_MISC_WINIMPLHELPER_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_MISC_WINIMPLHELPER_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+// converts a soffice label to a windows label
+// the following rules for character replacements
+// will be done:
+// '~' -> '&'
+// '~~' -> '~'
+// '&' -> '&&'
+OUString SOfficeToWindowsLabel( const OUString& aSOLabel );
+
+// converts a windows label to a soffice label
+// the following rules for character replacements
+// will be done:
+// '&' -> '~'
+// '&&' -> '&'
+// '~' -> '~~'
+OUString WindowsToSOfficeLabel( const OUString& aWinLabel );
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/asyncrequests.cxx b/fpicker/source/win32/asyncrequests.cxx
new file mode 100644
index 000000000..86b71cf51
--- /dev/null
+++ b/fpicker/source/win32/asyncrequests.cxx
@@ -0,0 +1,227 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "asyncrequests.hxx"
+#include <vcl/svapp.hxx>
+#include <vcl/winscheduler.hxx>
+#include <osl/mutex.hxx>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+static void lcl_sleep( ::osl::Condition& aCondition,
+ ::sal_Int32 nMilliSeconds )
+{
+ if (nMilliSeconds < 1)
+ aCondition.wait();
+ else
+ {
+ TimeValue aTime;
+ aTime.Seconds = (nMilliSeconds / 1000);
+ aTime.Nanosec = (nMilliSeconds % 1000) * 1000000;
+ aCondition.wait(&aTime);
+ }
+}
+
+void Request::wait( ::sal_Int32 nMilliSeconds )
+{
+ SolarMutexReleaser aReleaser;
+
+ lcl_sleep( m_aJoiner, nMilliSeconds );
+}
+
+void Request::waitProcessMessages()
+{
+ SolarMutexGuard aGuard;
+ while ( !m_aJoiner.check() )
+ Application::Yield();
+}
+
+void Request::notify()
+{
+ m_aJoiner.set();
+ // Make sure that main loop receives at least this message to return from GetMessage and recheck
+ // the condition, even in case when there's no visible application windows present, and thus no
+ // other messages might arrive to the main loop.
+ WinScheduler::PostDummyMessage();
+}
+
+AsyncRequests::AsyncRequests(const RequestHandlerRef& rHandler)
+ : ::cppu::BaseMutex( )
+ , ::osl::Thread ( )
+ , m_bFinish (false)
+ , m_rHandler (rHandler )
+ , m_lRequests ( )
+{
+}
+
+AsyncRequests::~AsyncRequests()
+{
+ // SYNCHRONIZED ->
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ m_bFinish = true;
+ }
+ // <- SYNCHRONIZED
+
+ // The static AsyncRequests aNotify in VistaFilePickerEventHandler::impl_sendEvent
+ // is destructed at DLL atexit. But it won't run, so needs no join and release of
+ // the already destructed SolarMutex, which would crash LO on exit.
+ if (isRunning())
+ {
+ // tdf#123502: make sure we actually hold the mutex before releasing it
+ // UNO directly destroys the VistaFilePicker object, so we need GUI protection in there.
+ // But since we redirect GUI stuff to the async thread we also have to release it, so we
+ // can join it, if the thread currently blocks on the SolarMutex.
+ SolarMutexGuard aGuard;
+ SolarMutexReleaser aReleaser;
+ join();
+ }
+}
+
+void AsyncRequests::triggerJobExecution()
+{
+ if ( ! isRunning())
+ create();
+ else
+ maWait.set();
+}
+
+void AsyncRequests::triggerRequestProcessMessages (const RequestRef& rRequest)
+{
+ // SYNCHRONIZED ->
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ m_lRequests.push(rRequest);
+ }
+ // <- SYNCHRONIZED
+
+ rRequest->waitProcessMessages();
+}
+
+void AsyncRequests::triggerRequestBlocked(const RequestRef& rRequest)
+{
+ // SYNCHRONIZED ->
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ m_lRequests.push(rRequest);
+ }
+ // <- SYNCHRONIZED
+
+ triggerJobExecution();
+
+ rRequest->wait();
+}
+
+void AsyncRequests::triggerRequestNonBlocked(const RequestRef& rRequest)
+{
+ // SYNCHRONIZED ->
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ m_lRequests.push(rRequest);
+ }
+ // <- SYNCHRONIZED
+
+ triggerJobExecution();
+}
+
+void AsyncRequests::triggerRequestDirectly(const RequestRef& rRequest)
+{
+ // SYNCHRONIZED ->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ RequestHandlerRef rHandler = m_rHandler;
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ if (rHandler != nullptr)
+ rHandler->doRequest(rRequest);
+}
+
+void AsyncRequests::triggerRequestThreadAware(const RequestRef& rRequest,
+ ::sal_Int16 nWait )
+{
+ oslThreadIdentifier nOurThreadId = getIdentifier();
+ oslThreadIdentifier nCallerThreadId = ::osl::Thread::getCurrentIdentifier();
+ SolarMutexGuard aGuard;
+ if (nOurThreadId == nCallerThreadId)
+ triggerRequestDirectly(rRequest);
+ else if (nWait == BLOCKED)
+ triggerRequestBlocked(rRequest);
+ else if (nWait == PROCESS_MESSAGES)
+ triggerRequestProcessMessages(rRequest);
+ else
+ triggerRequestNonBlocked(rRequest);
+}
+
+void SAL_CALL AsyncRequests::run()
+{
+ osl_setThreadName("fpicker::win32::vista::AsyncRequests");
+
+ static const ::sal_Int32 TIME_TO_WAIT_FOR_NEW_REQUESTS = 250;
+
+ // SYNCHRONIZED ->
+ ::osl::ResettableMutexGuard aLock(m_aMutex);
+ RequestHandlerRef rHandler = m_rHandler;
+ bool bFinished = m_bFinish;
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ if (rHandler != nullptr)
+ rHandler->before();
+
+ while ( ! bFinished)
+ {
+ // SYNCHRONIZED ->
+ aLock.reset();
+
+ RequestRef rRequest;
+ if ( ! m_lRequests.empty())
+ {
+ rRequest = m_lRequests.front();
+ m_lRequests.pop();
+ }
+ bFinished = m_bFinish;
+
+ aLock.clear();
+ // <- SYNCHRONIZED
+
+ if (rRequest == nullptr)
+ {
+ lcl_sleep(maWait, TIME_TO_WAIT_FOR_NEW_REQUESTS);
+ maWait.reset();
+ continue;
+ }
+
+ if (rHandler != nullptr)
+ {
+ rHandler->doRequest(rRequest);
+ rRequest->notify();
+ }
+ }
+
+ if (rHandler != nullptr)
+ rHandler->after();
+}
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/asyncrequests.hxx b/fpicker/source/win32/asyncrequests.hxx
new file mode 100644
index 000000000..5fbd7dde8
--- /dev/null
+++ b/fpicker/source/win32/asyncrequests.hxx
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_ASYNCREQUESTS_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_ASYNCREQUESTS_HXX
+
+#include <cppuhelper/basemutex.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <osl/conditn.hxx>
+#include <osl/thread.hxx>
+#include <osl/time.h>
+#include <queue>
+#include <memory>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+/** @todo document me
+ */
+class Request
+{
+
+ public:
+
+ static const ::sal_Int32 WAIT_INFINITE = 0;
+
+
+ // interface
+
+
+ public:
+
+
+ explicit Request()
+ : m_aJoiner ( )
+ , m_nRequest (-1)
+ , m_lArguments( )
+ {
+ m_aJoiner.reset();
+ }
+
+
+ virtual ~Request() {};
+
+
+ void setRequest(::sal_Int32 nRequest)
+ {
+ m_nRequest = nRequest;
+ }
+
+
+ ::sal_Int32 getRequest()
+ {
+ return m_nRequest;
+ }
+
+
+ void clearArguments()
+ {
+ m_lArguments.clear();
+ }
+
+
+ template< class TArgumentType >
+ void setArgument(const OUString& sName ,
+ const TArgumentType& aValue)
+ {
+ m_lArguments[sName] = css::uno::toAny(aValue);
+ }
+
+
+ template< class TArgumentType >
+ TArgumentType getArgumentOrDefault(const OUString& sName ,
+ const TArgumentType& aDefault)
+ {
+ return m_lArguments.getUnpackedValueOrDefault(sName, aDefault);
+ }
+
+ css::uno::Any getValue(OUString const & key) const
+ {
+ return m_lArguments.getValue(key);
+ }
+
+ void wait(::sal_Int32 nMilliSeconds = WAIT_INFINITE);
+
+ void waitProcessMessages();
+
+
+ void notify();
+
+
+ // member
+
+
+ private:
+
+ ::osl::Condition m_aJoiner;
+ ::sal_Int32 m_nRequest;
+ ::comphelper::SequenceAsHashMap m_lArguments;
+};
+
+typedef std::shared_ptr< Request > RequestRef;
+typedef std::queue< RequestRef > RequestQueue;
+
+
+class RequestHandler
+{
+ public:
+ virtual ~RequestHandler() {}
+ virtual void before() = 0;
+ virtual void doRequest(const RequestRef& rRequest) = 0;
+ virtual void after() = 0;
+};
+
+typedef std::shared_ptr< RequestHandler > RequestHandlerRef;
+
+
+/** @todo document me
+ */
+class AsyncRequests final: private ::cppu::BaseMutex
+ , public ::osl::Thread
+{
+ public:
+ static const ::sal_Int16 PROCESS_MESSAGES = 2;
+ static const ::sal_Int16 BLOCKED = 1;
+ static const ::sal_Int16 NON_BLOCKED = 0;
+
+
+ /** creates the new asynchronous request executor.
+ */
+ explicit AsyncRequests(const RequestHandlerRef& rHandler);
+
+ void setHandler(const RequestHandlerRef& rHandler)
+ {
+ m_rHandler = rHandler;
+ }
+
+ /// ensure the execution thread gets going.
+ void triggerJobExecution();
+
+
+ /** does nothing special / excepting to make sure our class won't be inline .-)
+ */
+ virtual ~AsyncRequests() override;
+
+
+ /** @todo document me
+ */
+ void triggerRequestProcessMessages (const RequestRef& rRequest);
+
+
+ /** @todo document me
+ */
+ void triggerRequestBlocked(const RequestRef& rRequest);
+
+
+ /** @todo document me
+ */
+ void triggerRequestNonBlocked(const RequestRef& rRequest);
+
+
+ /** @todo document me
+ */
+ void triggerRequestDirectly(const RequestRef& rRequest);
+
+
+ /** @todo document me
+ */
+ void triggerRequestThreadAware(const RequestRef& rRequest,
+ ::sal_Int16 nWait );
+
+ private:
+
+
+ /** our STA .-)
+ * Will run between start() & finish(). Internally it runs a loop ...
+ * waiting for requests. Every request will be executed synchronously
+ * in blocked mode.
+ */
+ virtual void SAL_CALL run() override;
+
+ private:
+
+ bool m_bFinish;
+ RequestHandlerRef m_rHandler;
+ RequestQueue m_lRequests;
+ osl::Condition maWait;
+};
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+#endif // INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_ASYNCREQUESTS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/comptr.hxx b/fpicker/source/win32/comptr.hxx
new file mode 100644
index 000000000..2469d8b5e
--- /dev/null
+++ b/fpicker/source/win32/comptr.hxx
@@ -0,0 +1,212 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_COMPTR_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_COMPTR_HXX
+
+#include <sal/types.h>
+#include <osl/diagnose.h>
+#include <shobjidl.h>
+
+template< class T_INTERFACE ,
+ REFIID P_IID = IID_NULL ,
+ REFCLSID P_CLSID = CLSID_NULL >
+class ComPtr
+{
+ public:
+
+
+ /** initialize com ptr with null.
+ */
+ ComPtr()
+ {
+ m_pInterface = nullptr;
+ }
+
+
+ /** initialize com ptr with given interface.
+ */
+ explicit ComPtr(T_INTERFACE* pInterface)
+ {
+ m_pInterface = pInterface;
+ if (m_pInterface)
+ m_pInterface->AddRef();
+ }
+
+
+ /** copy ctor.
+ */
+ ComPtr(const ComPtr< T_INTERFACE, P_IID, P_CLSID >& aCopy)
+ {
+ m_pInterface = aCopy.m_pInterface;
+ if (m_pInterface)
+ m_pInterface->AddRef();
+ }
+
+
+ /** initialize object by querying external object for the right interface.
+ */
+ explicit ComPtr(IUnknown* pIUnknown)
+ {
+ if (pIUnknown)
+ pIUnknown->QueryInterface(P_IID, (void**)&m_pInterface);
+ }
+
+
+ /** deinitialize com object right.
+ */
+ ~ComPtr()
+ {
+ release();
+ }
+
+ public:
+
+
+ HRESULT create()
+ {
+ return CoCreateInstance(P_CLSID, nullptr, CLSCTX_ALL, P_IID, reinterpret_cast<void**>(&m_pInterface));
+ }
+
+
+ operator T_INTERFACE*() const
+ {
+ return m_pInterface;
+ }
+
+
+ T_INTERFACE& operator*() const
+ {
+ return *m_pInterface;
+ }
+
+
+ T_INTERFACE** operator&()
+ {
+ return &m_pInterface;
+ }
+
+
+ T_INTERFACE* operator->() const
+ {
+ return m_pInterface;
+ }
+
+
+ T_INTERFACE* operator=(T_INTERFACE* pInterface)
+ {
+ if ( equals(pInterface) )
+ return m_pInterface;
+
+ m_pInterface->Release();
+ m_pInterface = pInterface;
+ if (m_pInterface)
+ m_pInterface->AddRef();
+
+ return m_pInterface;
+ }
+
+
+ T_INTERFACE* operator=(IUnknown* pIUnknown)
+ {
+ if (pIUnknown)
+ pIUnknown->QueryInterface(P_IID, (void**)&m_pInterface);
+ return m_pInterface;
+ }
+
+
+ T_INTERFACE* operator=(const ComPtr< T_INTERFACE, P_IID, P_CLSID >& aCopy)
+ {
+ m_pInterface = aCopy.m_pInterface;
+ if (m_pInterface)
+ m_pInterface->AddRef();
+
+ return m_pInterface;
+ }
+
+
+ T_INTERFACE* get() const
+ {
+ return m_pInterface;
+ }
+
+
+ void attach(T_INTERFACE* pInterface)
+ {
+ if (pInterface)
+ {
+ m_pInterface->Release();
+ m_pInterface = pInterface;
+ }
+ }
+
+
+ T_INTERFACE* detach()
+ {
+ T_INTERFACE* pInterface = m_pInterface;
+ m_pInterface = NULL;
+ return pInterface;
+ }
+
+
+ void release()
+ {
+ if (m_pInterface)
+ {
+ m_pInterface->Release();
+ m_pInterface = nullptr;
+ }
+ }
+
+ template< class T_QUERYINTERFACE >
+ HRESULT query(T_QUERYINTERFACE** pQuery)
+ {
+ return m_pInterface->QueryInterface(__uuidof(T_QUERYINTERFACE), reinterpret_cast<void**>(pQuery));
+ }
+
+ bool equals(IUnknown* pCheck)
+ {
+ if (
+ ( ! m_pInterface ) &&
+ ( ! pCheck )
+ )
+ return sal_True;
+
+ IUnknown* pCurrent = NULL;
+ m_pInterface->QueryInterface(IID_IUnknown, (void**)&pCurrent);
+
+ sal_Bool bEquals = (pCheck == pCurrent);
+ pCurrent->Release();
+
+ return bEquals;
+ }
+
+
+ bool is()
+ {
+ return (m_pInterface != nullptr);
+ }
+
+ private:
+ T_INTERFACE* m_pInterface;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/fps.component b/fpicker/source/win32/fps.component
new file mode 100644
index 000000000..80dac1a9b
--- /dev/null
+++ b/fpicker/source/win32/fps.component
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ prefix="fps_win32" xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.ui.dialogs.Win32FilePicker">
+ <service name="com.sun.star.ui.dialogs.SystemFilePicker"/>
+ </implementation>
+ <implementation name="com.sun.star.ui.dialogs.Win32FolderPicker">
+ <service name="com.sun.star.ui.dialogs.SystemFolderPicker"/>
+ </implementation>
+</component>
diff --git a/fpicker/source/win32/platform_vista.h b/fpicker/source/win32/platform_vista.h
new file mode 100644
index 000000000..a6e6d2121
--- /dev/null
+++ b/fpicker/source/win32/platform_vista.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_PLATFORM_VISTA_H
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_PLATFORM_VISTA_H
+
+#undef _WTL_NO_CSTRING
+
+#define _WTL_NO_CSTRING
+
+#if defined _MSC_VER
+#include <comip.h>
+#undef RGB
+#endif
+
+#ifdef _MSC_VER
+#if defined _M_IX86
+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/resourceprovider.cxx b/fpicker/source/win32/resourceprovider.cxx
new file mode 100644
index 000000000..883edf36d
--- /dev/null
+++ b/fpicker/source/win32/resourceprovider.cxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <rtl/ustrbuf.hxx>
+#include "resourceprovider.hxx"
+#include <osl/mutex.hxx>
+#include <fpicker/strings.hrc>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+#include <unotools/resmgr.hxx>
+#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <fpsofficeResMgr.hxx>
+
+using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
+using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
+
+#define FOLDERPICKER_TITLE 500
+#define FOLDER_PICKER_DEF_DESCRIPTION 501
+
+// we have to translate control ids to resource ids
+
+namespace {
+
+struct Entry
+{
+ sal_Int32 ctrlId;
+ const char* resId;
+};
+
+}
+
+Entry const CtrlIdToResIdTable[] = {
+ { CHECKBOX_AUTOEXTENSION, STR_SVT_FILEPICKER_AUTO_EXTENSION },
+ { CHECKBOX_PASSWORD, STR_SVT_FILEPICKER_PASSWORD },
+ { CHECKBOX_FILTEROPTIONS, STR_SVT_FILEPICKER_FILTER_OPTIONS },
+ { CHECKBOX_READONLY, STR_SVT_FILEPICKER_READONLY },
+ { CHECKBOX_LINK, STR_SVT_FILEPICKER_INSERT_AS_LINK },
+ { CHECKBOX_PREVIEW, STR_SVT_FILEPICKER_SHOW_PREVIEW },
+ { PUSHBUTTON_PLAY, STR_SVT_FILEPICKER_PLAY },
+ { LISTBOX_VERSION_LABEL, STR_SVT_FILEPICKER_VERSION },
+ { LISTBOX_TEMPLATE_LABEL, STR_SVT_FILEPICKER_TEMPLATES },
+ { LISTBOX_IMAGE_TEMPLATE_LABEL, STR_SVT_FILEPICKER_IMAGE_TEMPLATE },
+ { LISTBOX_IMAGE_ANCHOR_LABEL, STR_SVT_FILEPICKER_IMAGE_ANCHOR },
+ { CHECKBOX_SELECTION, STR_SVT_FILEPICKER_SELECTION },
+ { FOLDERPICKER_TITLE, STR_SVT_FOLDERPICKER_DEFAULT_TITLE },
+ { FOLDER_PICKER_DEF_DESCRIPTION, STR_SVT_FOLDERPICKER_DEFAULT_DESCRIPTION },
+ { CHECKBOX_GPGENCRYPTION, STR_SVT_FILEPICKER_GPGENCRYPT }
+};
+
+const sal_Int32 SIZE_TABLE = SAL_N_ELEMENTS( CtrlIdToResIdTable );
+
+static const char* CtrlIdToResId( sal_Int32 aControlId )
+{
+ const char* pResId = nullptr;
+
+ for ( sal_Int32 i = 0; i < SIZE_TABLE; i++ )
+ {
+ if ( CtrlIdToResIdTable[i].ctrlId == aControlId )
+ {
+ pResId = CtrlIdToResIdTable[i].resId;
+ break;
+ }
+ }
+
+ return pResId;
+}
+
+namespace CResourceProvider
+{
+ OUString getResString( sal_Int16 aId )
+ {
+ OUString aResOUString;
+ // translate the control id to a resource id
+ const char *pResId = CtrlIdToResId(aId);
+ if (pResId)
+ aResOUString = FpsResId(pResId);
+ return aResOUString;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/resourceprovider.hxx b/fpicker/source/win32/resourceprovider.hxx
new file mode 100644
index 000000000..a611d1aaf
--- /dev/null
+++ b/fpicker/source/win32/resourceprovider.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_MISC_RESOURCEPROVIDER_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_MISC_RESOURCEPROVIDER_HXX
+
+#include <sal/config.h>
+
+#include <memory>
+
+#include <sal/types.h>
+
+#include <rtl/ustring.hxx>
+
+namespace CResourceProvider
+{
+ OUString getResString(sal_Int16 aId);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/shared.hxx b/fpicker/source/win32/shared.hxx
new file mode 100644
index 000000000..be8813f32
--- /dev/null
+++ b/fpicker/source/win32/shared.hxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_SHARED_HXX
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_SHARED_HXX
+
+#include <rtl/ustring.hxx>
+
+const OUString BACKSLASH( "\\" );
+const OUString FILTER_SEPARATOR( "------------------------------------------" );
+const OUString ALL_FILES_WILDCARD( "*.*" );
+const bool ALLOW_DUPLICATES = true;
+
+#endif
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/vistatypes.h b/fpicker/source/win32/vistatypes.h
new file mode 100644
index 000000000..4271b0cea
--- /dev/null
+++ b/fpicker/source/win32/vistatypes.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTATYPES_H
+#define INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTATYPES_H
+
+#include "comptr.hxx"
+#include <shobjidl.h>
+
+namespace fpicker{
+namespace win32{
+namespace vista{
+
+
+// types, const etcpp.
+
+
+typedef ComPtr< IFileDialog , IID_IFileDialog > TFileDialog;
+typedef ComPtr< IFileOpenDialog , IID_IFileOpenDialog , CLSID_FileOpenDialog > TFileOpenDialog;
+typedef ComPtr< IFileSaveDialog , IID_IFileSaveDialog , CLSID_FileSaveDialog > TFileSaveDialog;
+typedef ComPtr< IFileDialogEvents , IID_IFileDialogEvents > TFileDialogEvents;
+typedef ComPtr< IFileDialogCustomize, IID_IFileDialogCustomize > TFileDialogCustomize;
+typedef TFileOpenDialog TFolderPickerDialog;
+
+} // namespace vista
+} // namespace win32
+} // namespace fpicker
+
+#endif // INCLUDED_FPICKER_SOURCE_WIN32_FILEPICKER_VISTATYPES_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/workbench/Test_fps.cxx b/fpicker/source/win32/workbench/Test_fps.cxx
new file mode 100644
index 000000000..b801fcef3
--- /dev/null
+++ b/fpicker/source/win32/workbench/Test_fps.cxx
@@ -0,0 +1,356 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/registry/XSimpleRegistry.hpp>
+#include <osl/file.hxx>
+
+#include <cppuhelper/servicefactory.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/types.h>
+#include <osl/diagnose.h>
+#include <com/sun/star/ui/dialogs/XFilePicker.hpp>
+#include <com/sun/star/ui/dialogs/XFilterManager.hpp>
+
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
+#include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
+#include <com/sun/star/ui/dialogs/XFilePreview.hpp>
+
+#include <osl/thread.h>
+
+#include <stdio.h>
+#if !defined WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include "..\FPServiceInfo.hxx"
+
+
+// namespaces
+
+
+using namespace ::cppu ;
+using namespace ::com::sun::star::uno ;
+using namespace ::com::sun::star::lang ;
+using namespace ::com::sun::star::ui::dialogs ;
+using namespace ::com::sun::star::ui::dialogs::TemplateDescription;
+
+using namespace ::com::sun::star::ui::dialogs::CommonFilePickerElementIds;
+using namespace ::com::sun::star::ui::dialogs::ExtendedFilePickerElementIds;
+using namespace ::com::sun::star::ui::dialogs::ListboxControlActions;
+
+using namespace std ;
+
+// forward
+
+void TestFilterManager( Reference< XFilePicker > xFilePicker );
+
+
+#define RDB_SYSPATH "D:\\Projects\\gsl\\sysui\\wntmsci7\\bin\\applicat.rdb"
+
+
+// global variables
+
+
+Reference< XMultiServiceFactory > g_xFactory;
+
+const OUString BMP_EXTENSION( "bmp" );
+
+
+// a test client
+
+
+class FilePickerListener : public WeakImplHelper< XFilePickerListener >
+{
+public:
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source )
+ throw(css::uno::RuntimeException);
+
+ // XFilePickerListener
+ virtual void SAL_CALL fileSelectionChanged( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException);
+
+ virtual void SAL_CALL directoryChanged( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException);
+
+ virtual OUString SAL_CALL helpRequested( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException);
+
+ virtual void SAL_CALL controlStateChanged( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException);
+
+ virtual void SAL_CALL dialogSizeChanged( )
+ throw (css::uno::RuntimeException);
+};
+
+void SAL_CALL FilePickerListener::disposing( const css::lang::EventObject& Source )
+ throw(css::uno::RuntimeException)
+{
+}
+
+void SAL_CALL FilePickerListener::fileSelectionChanged( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException)
+{
+ try
+ {
+ Reference< XFilePicker > rXFilePicker( aEvent.Source, UNO_QUERY );
+ Reference< XFilePreview > rXFilePreview( rXFilePicker, UNO_QUERY );
+
+ if ( !rXFilePreview.is( ) )
+ return;
+
+ Sequence< OUString > aFileList = rXFilePicker->getFiles( );
+ if ( 1 == aFileList.getLength( ) )
+ {
+ OUString FilePath = aFileList[0];
+
+ // detect file extension
+ sal_Int32 nIndex = FilePath.lastIndexOf( BMP_EXTENSION );
+ if ( (FilePath.getLength( ) - 3) == nIndex )
+ {
+ OUString FileSysPath;
+ ::osl::FileBase::getSystemPathFromFileURL(
+ FilePath, FileSysPath );
+
+ HANDLE hFile = CreateFileW(
+ FileSysPath.getStr( ),
+ GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return;
+
+ DWORD dwHighSize;
+ DWORD dwFileSize = GetFileSize (hFile, &dwHighSize) ;
+
+ if (dwHighSize)
+ {
+ CloseHandle (hFile) ;
+ return;
+ }
+
+ Sequence< sal_Int8 > aDIB( dwFileSize );
+
+ DWORD dwBytesRead;
+ sal_Bool bSuccess = ReadFile (hFile, aDIB.getArray( ), dwFileSize, &dwBytesRead, NULL) ;
+ CloseHandle (hFile);
+
+ BITMAPFILEHEADER* pbmfh = (BITMAPFILEHEADER*)aDIB.getConstArray( );
+ if (!bSuccess || (dwBytesRead != dwFileSize)
+ || (pbmfh->bfType != * (WORD *) "BM")
+ || (pbmfh->bfSize != dwFileSize))
+ {
+ return;
+ }
+
+ Any aAny;
+
+ aAny <<= aDIB;
+ rXFilePreview->setImage( 1, aAny );
+ }
+ }
+ }
+ catch( IllegalArgumentException& )
+ {
+ }
+}
+
+void SAL_CALL FilePickerListener::directoryChanged( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException)
+{
+ Reference< XFilePickerControlAccess > rFilePickerCtrlAccess( aEvent.Source, UNO_QUERY );
+}
+
+OUString SAL_CALL FilePickerListener::helpRequested( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException)
+{
+ return OUString( );
+}
+
+void SAL_CALL FilePickerListener::controlStateChanged( const css::ui::dialogs::FilePickerEvent& aEvent )
+ throw(css::uno::RuntimeException)
+{
+ try
+ {
+ Reference< XFilePickerControlAccess > rFPCtrlAccess( aEvent.Source, UNO_QUERY );
+
+ Any aValue;
+
+ OUString lbString( L"Ein Eintrag 1" );
+ aValue <<= lbString;
+ rFPCtrlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aValue );
+
+ lbString = L"Ein Eintrag 2";
+ aValue <<= lbString;
+ rFPCtrlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aValue );
+
+ lbString = L"Ein Eintrag 3";
+ aValue <<= lbString;
+ rFPCtrlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aValue );
+
+ sal_Int16 nSel = 1;
+ aValue <<= nSel;
+ rFPCtrlAccess->setValue( LISTBOX_VERSION, SET_SELECT_ITEM, aValue );
+
+ sal_Int32 nDel = 0;
+ aValue <<= nDel;
+ rFPCtrlAccess->setValue( LISTBOX_VERSION, DELETE_ITEM, aValue );
+ }
+ catch( ... )
+ {
+ }
+}
+
+void SAL_CALL FilePickerListener::dialogSizeChanged( )
+ throw(css::uno::RuntimeException)
+{
+}
+
+
+// main
+
+
+int SAL_CALL main(int nArgc, char* Argv[], char* Env[] )
+{
+ printf("Starting test of FPS-Service\n");
+
+
+ // get the global service-manager
+
+
+ // Get global factory for uno services.
+ Reference< XMultiServiceFactory > g_xFactory( createRegistryServiceFactory( RDB_SYSPATH ) );
+
+ // Print a message if an error occurred.
+ if ( g_xFactory.is() == sal_False )
+ {
+ OSL_FAIL("Can't create RegistryServiceFactory");
+ return(-1);
+ }
+
+
+ // try to get an Interface to a XFilePicker Service
+
+
+ Sequence< Any > arguments(1);
+ arguments[0] = makeAny( FILEOPEN_READONLY_VERSION );
+
+ Reference< XFilePicker > xFilePicker(
+ g_xFactory->createInstanceWithArguments(
+ FILE_PICKER_SERVICE_NAME, arguments ), UNO_QUERY );
+
+ // install a FilePicker notifier
+ Reference< XFilePickerListener > xFPListener(
+ static_cast< XFilePickerListener* >( new FilePickerListener()), UNO_QUERY );
+
+ Reference< XFilePickerNotifier > xFPNotifier( xFilePicker, UNO_QUERY );
+ if ( xFPNotifier.is( ) )
+ xFPNotifier->addFilePickerListener( xFPListener );
+
+ xFilePicker->setTitle( OUString("FileOpen Simple..."));
+ xFilePicker->setMultiSelectionMode( sal_True );
+ xFilePicker->setDefaultName( OUString("d:\\test2.sxw"));
+
+ OUString aDirURL;
+ OUString aSysPath = OStringToOUString( "d:\\ueaeoe", osl_getThreadTextEncoding( ) );
+ ::osl::FileBase::getFileURLFromSystemPath( aSysPath, aDirURL );
+ xFilePicker->setDisplayDirectory( aDirURL );
+
+ Reference< XFilterManager > xFilterMgr( xFilePicker, UNO_QUERY );
+ if ( xFilterMgr.is( ) )
+ {
+ xFilterMgr->appendFilter( L"Alle", L"*.*" );
+ xFilterMgr->appendFilter( L"BMP", L"*.bmp" );
+ xFilterMgr->appendFilter( L"SDW", L"*.sdw;*.sdc;*.sdi" );
+ xFilterMgr->appendFilter( L"SXW", L"*.sxw;*.sxi" );
+ }
+
+ Reference< XFilePickerControlAccess > xFPControlAccess( xFilePicker, UNO_QUERY );
+
+ Any aAny;
+ sal_Bool bChkState = sal_False;
+
+ aAny.setValue( &bChkState, cppu::UnoType<sal_Bool>::get());
+ xFPControlAccess->setValue( CHECKBOX_AUTOEXTENSION, 0, aAny );
+
+ OUString aVersion( L"Version 1" );
+ aAny <<= aVersion;
+ xFPControlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aAny );
+ xFPControlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aAny );
+ xFPControlAccess->setValue( LISTBOX_VERSION, ADD_ITEM, aAny );
+
+ xFilePicker->execute( );
+
+ sal_Bool bCheckState;
+ aAny = xFPControlAccess->getValue( CHECKBOX_AUTOEXTENSION, 0 );
+ if ( aAny.hasValue( ) )
+ bCheckState = *reinterpret_cast< const sal_Bool* >( aAny.getValue( ) );
+
+ aAny = xFPControlAccess->getValue( CHECKBOX_READONLY, 0 );
+ if ( aAny.hasValue( ) )
+ bCheckState = *reinterpret_cast< const sal_Bool* >( aAny.getValue( ) );
+
+ aAny = xFPControlAccess->getValue( LISTBOX_VERSION, GET_SELECTED_ITEM );
+ sal_Int32 nSel;
+ if ( aAny.hasValue( ) )
+ aAny >>= nSel;
+
+ aDirURL = xFilePicker->getDisplayDirectory( );
+ Sequence< OUString > aFileList = xFilePicker->getFiles( );
+ for ( int i = 0; i < aFileList.getLength( ); i++ )
+ {
+ OUString nextPath = aFileList[i];
+ }
+
+ if ( xFPNotifier.is( ) )
+ xFPNotifier->removeFilePickerListener( xFPListener );
+
+
+ // shutdown
+
+
+ // Cast factory to XComponent
+ Reference< XComponent > xComponent( g_xFactory, UNO_QUERY );
+
+ // Print a message if an error occurred.
+ if ( xComponent.is() == sal_False )
+ {
+ OSL_FAIL("Error shutting down");
+ }
+
+ // Dispose and clear factory
+ xComponent->dispose();
+ g_xFactory.clear();
+
+ printf("Test successful\n");
+
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/fpicker/source/win32/workbench/makefile.mk b/fpicker/source/win32/workbench/makefile.mk
new file mode 100644
index 000000000..5398300c1
--- /dev/null
+++ b/fpicker/source/win32/workbench/makefile.mk
@@ -0,0 +1,55 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+PRJ=..$/..$/..$/..
+
+PRJNAME=sysui
+TARGET=testfps
+LIBTARGET=NO
+TARGETTYPE=CUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+.IF "$(COM)" == "MSC"
+CFLAGS+=-GR -GX
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+
+OBJFILES=$(OBJ)$/test_fps.obj
+
+APP1TARGET=$(TARGET)
+APP1OBJS=$(OBJFILES)
+
+APP1STDLIBS+=\
+ $(CPPULIB)\
+ $(CPPUHELPERLIB)\
+ $(SALLIB)\
+ $(USER32LIB)\
+ $(OLE32LIB)
+
+APP1DEF=$(MISC)$/$(APP1TARGET).def
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+