1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _FILEOPENDLG_HXX_
29 #define _FILEOPENDLG_HXX_
30 
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
34 
35 #include <sal/types.h>
36 
37 #ifndef _RTL_USTRING_HXX_
38 #include <rtl/ustring>
39 #endif
40 #include <rtl/ustrbuf.hxx>
41 
42 #include "platform_xp.h"
43 #include "getfilenamewrapper.hxx"
44 
45 // because we don't want to import the new W2k platform skd
46 // into our build environment if have stolen the definition
47 // for the new OPENFILENAME structure from the new headers
48 
49 #ifndef _CDSIZEOF_STRUCT
50 #define _CDSIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
51 #endif
52 
53 typedef struct _tagOFNA {
54    DWORD        lStructSize;
55    HWND         hwndOwner;
56    HINSTANCE    hInstance;
57    LPCSTR       lpstrFilter;
58    LPSTR        lpstrCustomFilter;
59    DWORD        nMaxCustFilter;
60    DWORD        nFilterIndex;
61    LPSTR        lpstrFile;
62    DWORD        nMaxFile;
63    LPSTR        lpstrFileTitle;
64    DWORD        nMaxFileTitle;
65    LPCSTR       lpstrInitialDir;
66    LPCSTR       lpstrTitle;
67    DWORD        Flags;
68    WORD         nFileOffset;
69    WORD         nFileExtension;
70    LPCSTR       lpstrDefExt;
71    LPARAM       lCustData;
72    LPOFNHOOKPROC lpfnHook;
73    LPCSTR       lpTemplateName;
74 #ifdef _MAC
75    LPEDITMENU   lpEditInfo;
76    LPCSTR       lpstrPrompt;
77 #endif
78 #if (_WIN32_WINNT >= 0x0500)
79    void *		pvReserved;
80    DWORD        dwReserved;
81    DWORD        FlagsEx;
82 #endif // (_WIN32_WINNT >= 0x0500)
83 } _OPENFILENAMEA, *_LPOPENFILENAMEA;
84 
85 typedef struct _tagOFNW {
86    DWORD        lStructSize;
87    HWND         hwndOwner;
88    HINSTANCE    hInstance;
89    LPCWSTR      lpstrFilter;
90    LPWSTR       lpstrCustomFilter;
91    DWORD        nMaxCustFilter;
92    DWORD        nFilterIndex;
93    LPWSTR       lpstrFile;
94    DWORD        nMaxFile;
95    LPWSTR       lpstrFileTitle;
96    DWORD        nMaxFileTitle;
97    LPCWSTR      lpstrInitialDir;
98    LPCWSTR      lpstrTitle;
99    DWORD        Flags;
100    WORD         nFileOffset;
101    WORD         nFileExtension;
102    LPCWSTR      lpstrDefExt;
103    LPARAM       lCustData;
104    LPOFNHOOKPROC lpfnHook;
105    LPCWSTR      lpTemplateName;
106 #if (_WIN32_WINNT >= 0x0500)
107    void *       pvReserved;
108    DWORD        dwReserved;
109    DWORD        FlagsEx;
110 #endif // (_WIN32_WINNT >= 0x0500)
111 } _OPENFILENAMEW, *_LPOPENFILENAMEW;
112 
113 #ifdef UNICODE
114 typedef _OPENFILENAMEW _OPENFILENAME;
115 typedef _LPOPENFILENAMEW _LPOPENFILENAME;
116 #else
117 typedef _OPENFILENAMEA _OPENFILENAME;
118 typedef _LPOPENFILENAMEA _LPOPENFILENAME;
119 #endif // UNICODE
120 
121 #if (_WIN32_WINNT >= 0x0500)
122     #define _OPENFILENAME_SIZE_VERSION_400A  _CDSIZEOF_STRUCT(_OPENFILENAMEA,lpTemplateName)
123     #define _OPENFILENAME_SIZE_VERSION_400W  _CDSIZEOF_STRUCT(_OPENFILENAMEW,lpTemplateName)
124     #ifdef UNICODE
125         #define _OPENFILENAME_SIZE_VERSION_400  _OPENFILENAME_SIZE_VERSION_400W
126     #else
127         #define _OPENFILENAME_SIZE_VERSION_400  _OPENFILENAME_SIZE_VERSION_400A
128     #endif // !UNICODE
129 #else
130     #error _WIN32_WINNT seams not to be valid.
131 #endif // (_WIN32_WINNT >= 0x0500)
132 
133 
134 //-------------------------------------------------------------
135 // A simple wrapper class around the Win32 GetOpenFileName API.
136 // This class is not thread-safe and only one instance at a
137 // time is allowed
138 //-------------------------------------------------------------
139 
140 class CFileOpenDialog
141 {
142 public:
143 	// ctor
144 	// bFileOpenDialog idicates if we want a FileOpen or FileSave
145 	// dialog
146 	// dwFlags see OPENFILENAME
147 	// dwTemplateId - an ID for custom templates
148 	// hInstance    - an instance handle for the module
149 	// which provides the custom template, unused if dwTemplateId
150 	// is 0
151 	CFileOpenDialog(
152 		bool bFileOpenDialog = sal_True,
153 		sal_uInt32 dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
154 		sal_uInt32 dwTemplateId = 0,
155 		HINSTANCE hInstance = 0);
156 
157 	virtual ~CFileOpenDialog();
158 
159 	virtual void SAL_CALL setTitle(const rtl::OUString& aTitle);
160 
161 	// to set a filter string using the M$ format
162 	// e.g. FltName\0*.txt;*.rtf\0...\0\0
163 	void SAL_CALL setFilter(const rtl::OUString& aFilter);
164 
165 	// set the index of the current filter when the
166 	// dialog is about to shown, the index starts with 1
167 	// the function succeeded if the given filter index
168 	// is greater than zero and is a valid position
169 	// within filter string that was previously set
170 	bool SAL_CALL setFilterIndex(sal_uInt32 aIndex);
171 
172 	// get the index of the currently selected filter
173 	// the index of the returned filter starts with 1
174 	sal_uInt32 SAL_CALL getSelectedFilterIndex() const;
175 
176 	// set the name and optional the path of the
177 	// file that will be initially be shown when
178 	// the dialog will be displayed
179 	virtual void SAL_CALL setDefaultName(const rtl::OUString& aName);
180 
181 	// set the initial directory
182 	virtual void SAL_CALL setDisplayDirectory(const rtl::OUString& aDirectory);
183 
184 	// returns only the path of the selected file
185 	virtual rtl::OUString SAL_CALL getLastDisplayDirectory() const;
186 
187 	// returns the full file name including drive letter, path
188 	// file name and file extension
189 	virtual rtl::OUString SAL_CALL getFullFileName() const;
190 
191 	// returns the file name and the file extension without
192 	// drive letter and path
193 	rtl::OUString SAL_CALL getFileName() const;
194 
195 	// returns the file extension of the selected file
196 	rtl::OUString SAL_CALL getFileExtension();
197 
198 	// set a default extension, only the first three letters of
199 	// the given extension will be used; the given extension
200 	// should not contain a '.'
201 	void SAL_CALL setDefaultFileExtension(const rtl::OUString& aExtension);
202 
203 	// enables or disables the multiselection mode for
204 	// the FileOpen/FileSave dialog
205 	void SAL_CALL setMultiSelectionMode(bool bMode);
206 
207 	// returns whether multi-selection mode is enabled or not
208 	bool SAL_CALL getMultiSelectionMode() const;
209 
210 	// shows the dialog, calls preModal before
211 	// showing the dialog and postModal after
212 	// showing the dialog
213 	// the method returns:
214 	//  0 - when the dialog was canceled by the user
215 	//  1 - when the dialog was closed with ok
216 	// -1 - when an error occured
217 	sal_Int16 SAL_CALL doModal();
218 
219 	// returns the last dialog error that occured
220 	sal_uInt32 SAL_CALL getLastDialogError() const;
221 
222 	// retrievs the currently selected file
223 	// including path and drive information
224 	// can be called only if the dialog is
225 	// already displayed
226 	rtl::OUString SAL_CALL getCurrentFilePath() const;
227 
228 	// retrievs the currently selected folder
229 	rtl::OUString SAL_CALL getCurrentFolderPath() const;
230 
231 	// retrievs the currently selected file name
232 	// without drive and path
233 	rtl::OUString SAL_CALL getCurrentFileName() const;
234 
235 protected:
236 	// have to be overwritten when subclasses
237 	// want to do special pre- and post-modal
238 	// processing
239 
240 	// if preModal return true processing will
241 	// continue else doModal exit without showing
242 	// a dialog and returns -1
243 	virtual bool SAL_CALL preModal();
244 
245 	// post modal processing
246 	// the function should accept only values returned from
247 	// doModal and act appropriately
248 	virtual void SAL_CALL postModal(sal_Int16 nDialogResult);
249 
250 	// message handler, to be overwritten by subclasses
251 	virtual sal_uInt32 SAL_CALL onShareViolation(const rtl::OUString& aPathName);
252 	virtual sal_uInt32 SAL_CALL onFileOk();
253 	virtual void SAL_CALL onSelChanged(HWND hwndListBox);
254 	virtual void SAL_CALL onHelp();
255 
256 	// only called back if OFN_EXPLORER is set
257 	virtual void SAL_CALL onInitDone();
258 	virtual void SAL_CALL onFolderChanged();
259 	virtual void SAL_CALL onTypeChanged(sal_uInt32 nFilterIndex);
260 
261 	virtual void SAL_CALL onInitDialog(HWND hwndDlg) = 0;
262 
263 	virtual sal_uInt32 SAL_CALL onCtrlCommand(HWND hwndDlg, sal_uInt16 ctrlId, sal_uInt16 notifyCode);
264 
265 	sal_uInt32 SAL_CALL onWMNotify(HWND hwndChild, LPOFNOTIFYW lpOfNotify);
266 
267 	// we use non-virtual functions to do necessary work before
268 	// calling the virtual funtions (see Gamma: Template method)
269 	void SAL_CALL handleInitDialog(HWND hwndDlg, HWND hwndChild);
270 
271 protected:
272 
273 	// handle to the window of the
274 	// FileOpen/FileSave dialog
275 	// will be set on message
276 	// WM_INITDIALOG, before this
277 	// value is undefined
278 	HWND	m_hwndFileOpenDlg;
279 	HWND	m_hwndFileOpenDlgChild;
280 
281 	_OPENFILENAME	m_ofn;
282 
283     // we connect the instance with the dialog window using
284     // SetProp, with this function we can reconnect from
285     // callback functions to this instance
286     static CFileOpenDialog* SAL_CALL getCurrentInstance(HWND hwnd);
287 
288     void SAL_CALL centerPositionToParent() const;
289 
290 private:
291 	// FileOpen or FileSaveDialog
292 	bool			m_bFileOpenDialog;
293 	rtl::OUString	m_dialogTitle;
294 	rtl::OUString	m_displayDirectory;
295 	rtl::OUString	m_defaultExtension;
296 
297 	mutable	rtl::OUStringBuffer m_filterBuffer;
298 	mutable	rtl::OUStringBuffer m_fileTitleBuffer;
299 	mutable rtl::OUStringBuffer	m_helperBuffer;
300 	mutable rtl::OUStringBuffer m_fileNameBuffer;
301 
302     CGetFileNameWrapper m_GetFileNameWrapper;
303 
304     WNDPROC	    		m_pfnBaseDlgProc;
305 
306 	// callback function
307 	static unsigned int CALLBACK ofnHookProc(
308 		HWND hChildDlg, // handle to child dialog box
309 		unsigned int uiMsg,     // message identifier
310 		WPARAM wParam,  // message parameter
311 		LPARAM lParam   // message parameter
312 	);
313 
314     // we have to subclass the dialog in order
315     // to clean up the window property we are
316     // using to connect the window with a class
317     // instance in WM_NCDESTROY
318     static LRESULT CALLBACK BaseDlgProc(
319         HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam );
320 
321 private:
322 	// avoid copy and assignment
323 	CFileOpenDialog(const CFileOpenDialog&);
324 	CFileOpenDialog& operator=(const CFileOpenDialog&);
325 };
326 
327 #endif
328