summaryrefslogtreecommitdiff
path: root/fpicker/source/win32/filepicker/FileOpenDlg.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'fpicker/source/win32/filepicker/FileOpenDlg.cxx')
-rw-r--r--fpicker/source/win32/filepicker/FileOpenDlg.cxx695
1 files changed, 695 insertions, 0 deletions
diff --git a/fpicker/source/win32/filepicker/FileOpenDlg.cxx b/fpicker/source/win32/filepicker/FileOpenDlg.cxx
new file mode 100644
index 000000000000..73a757058e28
--- /dev/null
+++ b/fpicker/source/win32/filepicker/FileOpenDlg.cxx
@@ -0,0 +1,695 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_fpicker.hxx"
+
+//------------------------------------------------------------------------
+// includes
+//------------------------------------------------------------------------
+
+#include <tchar.h>
+#include <osl/diagnose.h>
+#include "../misc/WinImplHelper.hxx"
+#include "FileOpenDlg.hxx"
+
+//------------------------------------------------------------------------
+// constants
+//------------------------------------------------------------------------
+
+namespace /* private */
+{
+ // we choose such large buffers because the size of
+ // an single line edit field can be up to 32k; if
+ // a user has a multi selection FilePicker and selects
+ // a lot of files in a large directory we may reach this
+ // limit and don't want to get out of memory;
+ // another much more elegant way would be to subclass the
+ // FileOpen dialog and overload the BM_CLICK event of the
+ // OK button so that we determine the size of the text
+ // currently in the edit field and resize our buffer
+ // appropriately - in the future we will do this
+ const size_t MAX_FILENAME_BUFF_SIZE = 32000;
+ const size_t MAX_FILETITLE_BUFF_SIZE = 32000;
+ const size_t MAX_FILTER_BUFF_SIZE = 4096;
+
+ const LPTSTR CURRENT_INSTANCE = TEXT("CurrInst");
+
+ //------------------------------------------
+ // find an appropriate parent window
+ //------------------------------------------
+
+ inline bool is_current_process_window(HWND hwnd)
+ {
+ DWORD pid;
+ GetWindowThreadProcessId(hwnd, &pid);
+ return (pid == GetCurrentProcessId());
+ }
+
+ HWND choose_parent_window()
+ {
+ HWND hwnd_parent = GetForegroundWindow();
+ if (!is_current_process_window(hwnd_parent))
+ hwnd_parent = GetDesktopWindow();
+
+ return hwnd_parent;
+ }
+};
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+CFileOpenDialog::CFileOpenDialog(
+ bool bFileOpenDialog,
+ sal_uInt32 dwFlags,
+ sal_uInt32 dwTemplateId,
+ HINSTANCE hInstance) :
+ m_hwndFileOpenDlg(0),
+ m_hwndFileOpenDlgChild(0),
+ m_bFileOpenDialog(bFileOpenDialog),
+ m_filterBuffer(MAX_FILTER_BUFF_SIZE),
+ m_fileTitleBuffer(MAX_FILETITLE_BUFF_SIZE),
+ m_helperBuffer(MAX_FILENAME_BUFF_SIZE),
+ m_fileNameBuffer(MAX_FILENAME_BUFF_SIZE),
+ m_pfnBaseDlgProc(0)
+{
+ // initialize the OPENFILENAME struct
+ if (IsWindows2000Platform() || IsWindowsME())
+ {
+ ZeroMemory(&m_ofn, sizeof(m_ofn));
+ m_ofn.lStructSize = sizeof(m_ofn);
+ }
+ else // OSVER < Win2000
+ {
+ // the size of the OPENFILENAME structure is different
+ // under windows < win2000
+ ZeroMemory(&m_ofn, _OPENFILENAME_SIZE_VERSION_400);
+ m_ofn.lStructSize = _OPENFILENAME_SIZE_VERSION_400;
+ }
+
+ // 0x02000000 for #97681, sfx will make the entry into
+ // the recent document list
+ m_ofn.Flags |= dwFlags |
+ OFN_EXPLORER |
+ OFN_ENABLEHOOK |
+ OFN_HIDEREADONLY |
+ OFN_PATHMUSTEXIST |
+ OFN_FILEMUSTEXIST |
+ OFN_OVERWRITEPROMPT |
+ OFN_ENABLESIZING |
+ OFN_DONTADDTORECENT; // 0x02000000 -> OFN_DONTADDTORECENT only available with new platform sdk
+
+ // it is a little hack but how else could
+ // we get a parent window (using a vcl window?)
+ m_ofn.hwndOwner = choose_parent_window();
+
+ m_ofn.lpstrFile = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileNameBuffer.getStr()));
+ m_ofn.nMaxFile = m_fileNameBuffer.getCapacity();
+
+ m_ofn.lpstrFileTitle = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileTitleBuffer.getStr()));
+ m_ofn.nMaxFileTitle = m_fileTitleBuffer.getCapacity();
+
+ m_ofn.lpfnHook = CFileOpenDialog::ofnHookProc;
+
+ // set a custom template
+
+ if (dwTemplateId)
+ {
+ OSL_ASSERT(hInstance);
+
+ m_ofn.Flags |= OFN_ENABLETEMPLATE;
+ m_ofn.lpTemplateName = MAKEINTRESOURCE(dwTemplateId);
+ m_ofn.hInstance = hInstance;
+ }
+
+ // set a pointer to myself as ofn parameter
+ m_ofn.lCustData = reinterpret_cast<long>(this);
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+CFileOpenDialog::~CFileOpenDialog()
+{
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::setTitle(const rtl::OUString& aTitle)
+{
+ m_dialogTitle = aTitle;
+ m_ofn.lpstrTitle = reinterpret_cast<LPCTSTR>(m_dialogTitle.getStr());
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void CFileOpenDialog::setFilter(const rtl::OUString& aFilter)
+{
+ // Format is like
+ // "*.TXT" or multiple separate by ';' like "*.TXT;*.DOC;*.SXW"
+ // Do not include spaces in the pattern string
+ m_filterBuffer.ensureCapacity(aFilter.getLength());
+ m_filterBuffer.setLength(0);
+ m_filterBuffer.append(aFilter);
+ m_ofn.lpstrFilter = reinterpret_cast<LPCTSTR>(m_filterBuffer.getStr());
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+bool CFileOpenDialog::setFilterIndex(sal_uInt32 aIndex)
+{
+ OSL_ASSERT(aIndex > 0);
+ m_ofn.nFilterIndex = aIndex;
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+sal_uInt32 CFileOpenDialog::getSelectedFilterIndex() const
+{
+ return m_ofn.nFilterIndex;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::setDefaultName(const rtl::OUString& aName)
+{
+ m_fileNameBuffer.setLength(0);
+ m_fileNameBuffer.append(aName);
+ m_ofn.lpstrFile = reinterpret_cast<LPTSTR>(const_cast<sal_Unicode*>(m_fileNameBuffer.getStr()));
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::setDisplayDirectory(const rtl::OUString& aDirectory)
+{
+ m_displayDirectory = aDirectory;
+ m_ofn.lpstrInitialDir = reinterpret_cast<LPCTSTR>(m_displayDirectory.getStr());
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL CFileOpenDialog::getLastDisplayDirectory() const
+{
+ return m_displayDirectory;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL CFileOpenDialog::getFullFileName() const
+{
+ return rtl::OUString(m_fileNameBuffer.getStr(),
+ _wcslenex(m_fileNameBuffer.getStr()));
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL CFileOpenDialog::getFileName() const
+{
+ return rtl::OUString(m_fileTitleBuffer);
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+rtl::OUString CFileOpenDialog::getFileExtension()
+{
+ if (m_ofn.nFileExtension)
+ return rtl::OUString(m_fileNameBuffer.getStr() + m_ofn.nFileExtension,
+ rtl_ustr_getLength(m_fileNameBuffer.getStr() + m_ofn.nFileExtension));
+
+ return rtl::OUString();
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void CFileOpenDialog::setDefaultFileExtension(const rtl::OUString& aExtension)
+{
+ m_defaultExtension = aExtension;
+ m_ofn.lpstrDefExt = reinterpret_cast<LPCTSTR>(m_defaultExtension.getStr());
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::setMultiSelectionMode(bool bMode)
+{
+ if (bMode)
+ m_ofn.Flags |= OFN_ALLOWMULTISELECT;
+ else
+ m_ofn.Flags &= ~OFN_ALLOWMULTISELECT;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+bool SAL_CALL CFileOpenDialog::getMultiSelectionMode() const
+{
+ return ((m_ofn.Flags & OFN_ALLOWMULTISELECT) > 0);
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+sal_Int16 SAL_CALL CFileOpenDialog::doModal()
+{
+ sal_Int16 nRC = -1;
+
+ // pre-processing
+ if (preModal())
+ {
+ bool bRet;
+
+ if (m_bFileOpenDialog)
+ bRet = m_GetFileNameWrapper.getOpenFileName(
+ reinterpret_cast<LPOPENFILENAME>(&m_ofn));
+ else
+ bRet = m_GetFileNameWrapper.getSaveFileName(
+ reinterpret_cast<LPOPENFILENAME>(&m_ofn));
+
+ nRC = 1;
+
+ if (!bRet)
+ nRC = (0 == m_GetFileNameWrapper.commDlgExtendedError()) ? 0 : -1;
+
+ // post-processing
+ postModal(nRC);
+ }
+
+ return nRC;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+sal_uInt32 SAL_CALL CFileOpenDialog::getLastDialogError() const
+{
+ return CommDlgExtendedError();
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+bool SAL_CALL CFileOpenDialog::preModal()
+{
+ return sal_True;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::postModal(sal_Int16 nDialogResult)
+{
+ OSL_ASSERT((-1 <= nDialogResult) && (nDialogResult <= 1));
+
+ if (1 == nDialogResult)
+ {
+ // Attention: assuming that nFileOffset is always greater 0 because under
+ // Windows there is always a drive letter or a server in a complete path
+ // the OPENFILENAME docu never says that nFileOffset can be 0
+ m_displayDirectory = rtl::OUString(reinterpret_cast<const sal_Unicode*>(m_ofn.lpstrFile),m_ofn.nFileOffset);
+ }
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFilePath() const
+{
+ OSL_ASSERT(IsWindow(m_hwndFileOpenDlg));
+
+ LPARAM nLen = SendMessage(
+ m_hwndFileOpenDlg,
+ CDM_GETFILEPATH,
+ m_helperBuffer.getCapacity(),
+ reinterpret_cast<LPARAM>(m_helperBuffer.getStr()));
+
+ if (nLen > 0)
+ {
+ m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1);
+ return rtl::OUString(m_helperBuffer);
+ }
+ return rtl::OUString();
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFolderPath() const
+{
+ OSL_ASSERT(IsWindow(m_hwndFileOpenDlg));
+
+ LPARAM nLen = SendMessage(
+ m_hwndFileOpenDlg,
+ CDM_GETFOLDERPATH,
+ m_helperBuffer.getCapacity(),
+ reinterpret_cast<LPARAM>(m_helperBuffer.getStr()));
+
+ if (nLen > 0)
+ {
+ m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1);
+ return rtl::OUString(m_helperBuffer);
+ }
+ return rtl::OUString();
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL CFileOpenDialog::getCurrentFileName() const
+{
+ OSL_ASSERT(IsWindow(m_hwndFileOpenDlg));
+
+ LPARAM nLen = SendMessage(
+ m_hwndFileOpenDlg,
+ CDM_GETSPEC,
+ m_helperBuffer.getCapacity(),
+ reinterpret_cast<LPARAM>(m_helperBuffer.getStr()));
+
+ if (nLen > 0)
+ {
+ m_helperBuffer.setLength((nLen * sizeof(sal_Unicode)) - 1);
+ return rtl::OUString(m_helperBuffer);
+ }
+ return rtl::OUString();
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+sal_uInt32 SAL_CALL CFileOpenDialog::onShareViolation(const rtl::OUString&)
+{
+ return 0;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+sal_uInt32 SAL_CALL CFileOpenDialog::onFileOk()
+{
+ return 0;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::onSelChanged(HWND)
+{
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::onHelp()
+{
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::onInitDone()
+{
+ centerPositionToParent();
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::onFolderChanged()
+{
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::onTypeChanged(sal_uInt32)
+{
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+sal_uInt32 SAL_CALL CFileOpenDialog::onCtrlCommand(HWND, sal_uInt16, sal_uInt16)
+{
+ return 0;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+sal_uInt32 SAL_CALL CFileOpenDialog::onWMNotify( HWND, LPOFNOTIFY lpOfNotify )
+{
+ switch(lpOfNotify->hdr.code)
+ {
+ case CDN_SHAREVIOLATION:
+ return onShareViolation(reinterpret_cast<const sal_Unicode*>(lpOfNotify->pszFile));
+
+ case CDN_FILEOK:
+ return onFileOk();
+
+ case CDN_SELCHANGE:
+ onSelChanged(lpOfNotify->hdr.hwndFrom);
+ break;
+
+ case CDN_HELP:
+ onHelp();
+ break;
+
+ case CDN_INITDONE:
+ onInitDone();
+ break;
+
+ case CDN_FOLDERCHANGE:
+ onFolderChanged();
+ break;
+
+ case CDN_TYPECHANGE:
+ m_ofn.nFilterIndex = lpOfNotify->lpOFN->nFilterIndex;
+ onTypeChanged(lpOfNotify->lpOFN->nFilterIndex);
+ break;
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::handleInitDialog(HWND hwndDlg, HWND hwndChild)
+{
+ m_hwndFileOpenDlg = hwndDlg;
+ m_hwndFileOpenDlgChild = hwndChild;
+
+ OSL_ASSERT(GetParent(hwndChild) == hwndDlg);
+
+ // calling virtual function which the
+ // client can overload
+ onInitDialog(hwndDlg);
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+unsigned int CALLBACK CFileOpenDialog::ofnHookProc(
+ HWND hChildDlg, unsigned int uiMsg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndDlg = GetParent(hChildDlg);
+ CFileOpenDialog* pImpl = NULL;
+
+ switch( uiMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ _LPOPENFILENAME lpofn = reinterpret_cast<_LPOPENFILENAME>(lParam);
+ pImpl = reinterpret_cast<CFileOpenDialog*>(lpofn->lCustData);
+ OSL_ASSERT(pImpl);
+
+ // subclass the base dialog for WM_NCDESTROY processing
+ pImpl->m_pfnBaseDlgProc =
+ reinterpret_cast<WNDPROC>(
+ SetWindowLong(
+ hwndDlg,
+ GWL_WNDPROC,
+ reinterpret_cast<LONG>(CFileOpenDialog::BaseDlgProc)));
+ // connect the instance handle to the window
+ SetProp(hwndDlg, CURRENT_INSTANCE, pImpl);
+ pImpl->handleInitDialog(hwndDlg, hChildDlg);
+ }
+ return 0;
+
+ case WM_NOTIFY:
+ {
+ pImpl = getCurrentInstance(hwndDlg);
+ return pImpl->onWMNotify(
+ hChildDlg, reinterpret_cast<LPOFNOTIFY>(lParam));
+ }
+
+ case WM_COMMAND:
+ {
+ pImpl = getCurrentInstance(hwndDlg);
+ OSL_ASSERT(pImpl);
+
+ return pImpl->onCtrlCommand(
+ hChildDlg, LOWORD(wParam), HIWORD(lParam));
+ }
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+LRESULT CALLBACK CFileOpenDialog::BaseDlgProc(
+ HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam)
+{
+ CFileOpenDialog* pImpl = 0;
+
+ if (WM_NCDESTROY == wMessage)
+ {
+ pImpl = reinterpret_cast<CFileOpenDialog*>(
+ RemoveProp(hWnd,CURRENT_INSTANCE));
+
+ SetWindowLong(hWnd, GWL_WNDPROC,
+ reinterpret_cast<LONG>(pImpl->m_pfnBaseDlgProc));
+ }
+ else
+ {
+ pImpl = getCurrentInstance(hWnd);
+ }
+
+ OSL_ASSERT(pImpl);
+
+ return CallWindowProc(
+ reinterpret_cast<WNDPROC>(pImpl->m_pfnBaseDlgProc),
+ hWnd,wMessage,wParam,lParam);
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+CFileOpenDialog* SAL_CALL CFileOpenDialog::getCurrentInstance(HWND hwnd)
+{
+ OSL_ASSERT(IsWindow( hwnd));
+ return reinterpret_cast<CFileOpenDialog*>(
+ GetProp(hwnd, CURRENT_INSTANCE));
+}
+
+//------------------------------------------------------------------------
+//
+//------------------------------------------------------------------------
+
+void SAL_CALL CFileOpenDialog::centerPositionToParent() const
+{
+ OSL_PRECOND(IsWindow(m_hwndFileOpenDlg), "no dialog window, call method only after or in onInitDone");
+
+ HWND hwndParent = m_ofn.hwndOwner;
+
+ if (!IsWindow(hwndParent))
+ hwndParent = GetDesktopWindow();
+
+ OSL_ASSERT(IsWindow(hwndParent));
+
+ RECT rcPar;
+ GetWindowRect(hwndParent, &rcPar);
+
+ RECT rcDlg;
+ GetWindowRect(m_hwndFileOpenDlg, &rcDlg);
+
+ int lDlgW = rcDlg.right - rcDlg.left;
+ int lDlgH = rcDlg.bottom - rcDlg.top;
+
+ int x = (rcPar.left + rcPar.right - lDlgW) / 2;
+ int y = (rcPar.top + rcPar.bottom - lDlgH) / 2;
+
+ HDC hdc = GetDC(m_hwndFileOpenDlg);
+
+ int hResol = GetDeviceCaps(hdc, HORZRES);
+ int vResol = GetDeviceCaps(hdc, VERTRES);
+
+ ReleaseDC(m_hwndFileOpenDlg, hdc);
+
+ if (x < 0)
+ x = 0;
+ else if ((x + lDlgW) > hResol)
+ x = hResol - lDlgW;
+
+ if (y < 0)
+ y = 0;
+ else if ((y + lDlgH) > vResol)
+ y = vResol - lDlgH;
+
+ SetWindowPos(
+ m_hwndFileOpenDlg,
+ NULL, x, y, 0, 0,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE );
+}