author | asaha |
Wed, 04 May 2011 16:39:05 -0700 | |
changeset 9851 | 23bd656b112e |
parent 9829 | 59c2c48a4b9e |
parent 9201 | c2c745bb19a6 |
child 10411 | f63e5bab1676 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
7668 | 2 |
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
#include "awt.h" |
|
27 |
#include "awt_FileDialog.h" |
|
28 |
#include "awt_Dialog.h" |
|
29 |
#include "awt_Toolkit.h" |
|
30 |
#include "ComCtl32Util.h" |
|
31 |
#include <commdlg.h> |
|
32 |
#include <cderr.h> |
|
33 |
#include <shlobj.h> |
|
34 |
||
35 |
||
36 |
/************************************************************************ |
|
37 |
* AwtFileDialog fields |
|
38 |
*/ |
|
39 |
||
40 |
/* WFileDialogPeer ids */ |
|
41 |
jfieldID AwtFileDialog::parentID; |
|
42 |
jfieldID AwtFileDialog::fileFilterID; |
|
43 |
jmethodID AwtFileDialog::setHWndMID; |
|
44 |
jmethodID AwtFileDialog::handleSelectedMID; |
|
45 |
jmethodID AwtFileDialog::handleCancelMID; |
|
46 |
jmethodID AwtFileDialog::checkFilenameFilterMID; |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
47 |
jmethodID AwtFileDialog::isMultipleModeMID; |
2 | 48 |
|
49 |
/* FileDialog ids */ |
|
50 |
jfieldID AwtFileDialog::modeID; |
|
51 |
jfieldID AwtFileDialog::dirID; |
|
52 |
jfieldID AwtFileDialog::fileID; |
|
53 |
jfieldID AwtFileDialog::filterID; |
|
54 |
||
55 |
/* Localized filter string */ |
|
56 |
#define MAX_FILTER_STRING 128 |
|
57 |
static TCHAR s_fileFilterString[MAX_FILTER_STRING]; |
|
58 |
/* Non-localized suffix of the filter string */ |
|
59 |
static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0"); |
|
60 |
||
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
61 |
// Default limit of the output buffer. |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
62 |
#define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1 |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
63 |
#define MULTIPLE_MODE_BUFFER_LIMIT 32768 |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
64 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
65 |
// The name of the property holding the pointer to the OPENFILENAME structure. |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
66 |
static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN"); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
67 |
|
2 | 68 |
/***********************************************************************/ |
69 |
||
70 |
void |
|
71 |
AwtFileDialog::Initialize(JNIEnv *env, jstring filterDescription) |
|
72 |
{ |
|
73 |
int length = env->GetStringLength(filterDescription); |
|
74 |
DASSERT(length + 1 < MAX_FILTER_STRING); |
|
1954 | 75 |
LPCTSTR tmp = JNU_GetStringPlatformChars(env, filterDescription, NULL); |
2 | 76 |
_tcscpy(s_fileFilterString, tmp); |
77 |
JNU_ReleaseStringPlatformChars(env, filterDescription, tmp); |
|
78 |
||
79 |
//AdditionalString should be terminated by two NULL characters (Windows |
|
80 |
//requirement), so we have to organize the following cycle and use memcpy |
|
81 |
//unstead of, for example, strcat. |
|
82 |
LPTSTR s = s_fileFilterString; |
|
83 |
while (*s) { |
|
84 |
++s; |
|
85 |
DASSERT(s < s_fileFilterString + MAX_FILTER_STRING); |
|
86 |
} |
|
87 |
DASSERT(s + sizeof(s_additionalString) < s_fileFilterString + MAX_FILTER_STRING); |
|
88 |
memcpy(s, s_additionalString, sizeof(s_additionalString)); |
|
89 |
} |
|
90 |
||
91 |
LRESULT CALLBACK FileDialogWndProc(HWND hWnd, UINT message, |
|
92 |
WPARAM wParam, LPARAM lParam) |
|
93 |
{ |
|
94 |
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
95 |
||
96 |
switch (message) { |
|
97 |
case WM_COMMAND: { |
|
98 |
if (LOWORD(wParam) == IDCANCEL) |
|
99 |
{ |
|
100 |
// Unlike Print/Page dialogs, we only handle IDCANCEL here and |
|
101 |
// don't handle IDOK. This is because user can press OK button |
|
102 |
// when no file is selected, and the dialog is not closed. So |
|
103 |
// OK button is handled in the CDN_FILEOK notification handler |
|
104 |
// (see FileDialogHookProc below) |
|
105 |
jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp)); |
|
106 |
env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); |
|
107 |
} |
|
108 |
break; |
|
109 |
} |
|
110 |
} |
|
111 |
||
2456
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
112 |
WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(hWnd, NativeDialogWndProcProp)); |
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
113 |
return ComCtl32Util::GetInstance().DefWindowProc(lpfnWndProc, hWnd, message, wParam, lParam); |
2 | 114 |
} |
115 |
||
116 |
static UINT_PTR CALLBACK |
|
117 |
FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) |
|
118 |
{ |
|
119 |
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
120 |
||
121 |
TRY; |
|
122 |
||
123 |
HWND parent = ::GetParent(hdlg); |
|
124 |
||
125 |
switch(uiMsg) { |
|
126 |
case WM_INITDIALOG: { |
|
127 |
OPENFILENAME *ofn = (OPENFILENAME *)lParam; |
|
128 |
jobject peer = (jobject)(ofn->lCustData); |
|
129 |
env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, |
|
130 |
(jlong)parent); |
|
131 |
::SetProp(parent, ModalDialogPeerProp, reinterpret_cast<HANDLE>(peer)); |
|
132 |
||
133 |
// fix for 4508670 - disable CS_SAVEBITS |
|
134 |
DWORD style = ::GetClassLong(hdlg,GCL_STYLE); |
|
135 |
::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS); |
|
136 |
||
137 |
// set appropriate icon for parentless dialogs |
|
138 |
jobject awtParent = env->GetObjectField(peer, AwtFileDialog::parentID); |
|
139 |
if (awtParent == NULL) { |
|
140 |
::SendMessage(parent, WM_SETICON, (WPARAM)ICON_BIG, |
|
141 |
(LPARAM)AwtToolkit::GetInstance().GetAwtIcon()); |
|
142 |
} else { |
|
143 |
env->DeleteLocalRef(awtParent); |
|
144 |
} |
|
145 |
||
146 |
// subclass dialog's parent to receive additional messages |
|
2456
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
147 |
WNDPROC lpfnWndProc = ComCtl32Util::GetInstance().SubclassHWND(parent, |
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
148 |
FileDialogWndProc); |
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
149 |
::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc)); |
2 | 150 |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
151 |
::SetProp(parent, OpenFileNameProp, (void *)lParam); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
152 |
|
2 | 153 |
break; |
154 |
} |
|
155 |
case WM_DESTROY: { |
|
2456
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
156 |
WNDPROC lpfnWndProc = (WNDPROC)(::GetProp(parent, NativeDialogWndProcProp)); |
2 | 157 |
ComCtl32Util::GetInstance().UnsubclassHWND(parent, |
158 |
FileDialogWndProc, |
|
2456
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
159 |
lpfnWndProc); |
2 | 160 |
::RemoveProp(parent, ModalDialogPeerProp); |
2456
45ee87a35349
6792023: Print suspends on Windows 2000 Pro since 6u12 b01
dcherepanov
parents:
1954
diff
changeset
|
161 |
::RemoveProp(parent, NativeDialogWndProcProp); |
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
162 |
::RemoveProp(parent, OpenFileNameProp); |
2 | 163 |
break; |
164 |
} |
|
165 |
case WM_NOTIFY: { |
|
166 |
OFNOTIFYEX *notifyEx = (OFNOTIFYEX *)lParam; |
|
167 |
if (notifyEx) { |
|
168 |
jobject peer = (jobject)(::GetProp(parent, ModalDialogPeerProp)); |
|
169 |
if (notifyEx->hdr.code == CDN_INCLUDEITEM) { |
|
170 |
LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl; |
|
171 |
// Get the filename and directory |
|
172 |
TCHAR szPath[MAX_PATH]; |
|
1954 | 173 |
if (!::SHGetPathFromIDList(pidl, szPath)) { |
2 | 174 |
return TRUE; |
175 |
} |
|
176 |
jstring strPath = JNU_NewStringPlatform(env, szPath); |
|
177 |
// Call FilenameFilter.accept with path and filename |
|
178 |
UINT uRes = (env->CallBooleanMethod(peer, |
|
179 |
AwtFileDialog::checkFilenameFilterMID, strPath) == JNI_TRUE); |
|
180 |
env->DeleteLocalRef(strPath); |
|
181 |
return uRes; |
|
182 |
} else if (notifyEx->hdr.code == CDN_FILEOK) { |
|
183 |
// This notification is sent when user selects some file and presses |
|
184 |
// OK button; it is not sent when no file is selected. So it's time |
|
185 |
// to unblock all the windows blocked by this dialog as it will |
|
186 |
// be closed soon |
|
187 |
env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
188 |
} else if (notifyEx->hdr.code == CDN_SELCHANGE) { |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
189 |
// reallocate the buffer if the buffer is too small |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
190 |
LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
191 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
192 |
UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) + |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
193 |
CommDlg_OpenSave_GetFolderPath(parent, NULL, 0); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
194 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
195 |
if (lpofn->nMaxFile < nLength) |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
196 |
{ |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
197 |
// allocate new buffer |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
198 |
LPTSTR newBuffer = new TCHAR[nLength]; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
199 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
200 |
if (newBuffer) { |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
201 |
memset(newBuffer, 0, nLength * sizeof(TCHAR)); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
202 |
LPTSTR oldBuffer = lpofn->lpstrFile; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
203 |
lpofn->lpstrFile = newBuffer; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
204 |
lpofn->nMaxFile = nLength; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
205 |
// free the previously allocated buffer |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
206 |
if (oldBuffer) { |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
207 |
delete[] oldBuffer; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
208 |
} |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
209 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
210 |
} |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
211 |
} |
2 | 212 |
} |
213 |
} |
|
214 |
break; |
|
215 |
} |
|
216 |
} |
|
217 |
||
218 |
return FALSE; |
|
219 |
||
220 |
CATCH_BAD_ALLOC_RET(TRUE); |
|
221 |
} |
|
222 |
||
223 |
void |
|
224 |
AwtFileDialog::Show(void *p) |
|
225 |
{ |
|
226 |
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
227 |
jobject peer; |
|
228 |
LPTSTR fileBuffer = NULL; |
|
229 |
LPTSTR currentDirectory = NULL; |
|
230 |
jint mode = 0; |
|
231 |
BOOL result = FALSE; |
|
232 |
DWORD dlgerr; |
|
233 |
jstring directory = NULL; |
|
234 |
jstring title = NULL; |
|
235 |
jstring file = NULL; |
|
236 |
jobject fileFilter = NULL; |
|
237 |
jobject target = NULL; |
|
238 |
jobject parent = NULL; |
|
239 |
AwtComponent* awtParent = NULL; |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
240 |
jboolean multipleMode = JNI_FALSE; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
241 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
242 |
OPENFILENAME ofn; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
243 |
memset(&ofn, 0, sizeof(ofn)); |
2 | 244 |
|
245 |
/* |
|
246 |
* There's a situation (see bug 4906972) when InvokeFunction (by which this method is called) |
|
247 |
* returnes earlier than this method returnes. Probably it's caused due to ReplyMessage system call. |
|
248 |
* So for the avoidance of this mistiming we need to make new global reference here |
|
249 |
* (not local as it's used by the hook) and then manage it independently of the calling thread. |
|
250 |
*/ |
|
251 |
peer = env->NewGlobalRef((jobject)p); |
|
252 |
||
253 |
try { |
|
254 |
DASSERT(peer); |
|
255 |
target = env->GetObjectField(peer, AwtObject::targetID); |
|
256 |
parent = env->GetObjectField(peer, AwtFileDialog::parentID); |
|
257 |
if (parent != NULL) { |
|
258 |
awtParent = (AwtComponent *)JNI_GET_PDATA(parent); |
|
259 |
} |
|
260 |
// DASSERT(awtParent); |
|
261 |
title = (jstring)(env)->GetObjectField(target, AwtDialog::titleID); |
|
262 |
HWND hwndOwner = awtParent ? awtParent->GetHWnd() : NULL; |
|
263 |
||
264 |
if (title == NULL || env->GetStringLength(title)==0) { |
|
9201
c2c745bb19a6
7031854: JCK 7 test FileDialogTest0001 fails on Windows with Russian locale
dav
parents:
7668
diff
changeset
|
265 |
title = JNU_NewStringPlatform(env, L" "); |
2 | 266 |
} |
267 |
||
268 |
JavaStringBuffer titleBuffer(env, title); |
|
269 |
directory = |
|
270 |
(jstring)env->GetObjectField(target, AwtFileDialog::dirID); |
|
271 |
JavaStringBuffer directoryBuffer(env, directory); |
|
272 |
||
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
273 |
multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
274 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
275 |
UINT bufferLimit; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
276 |
if (multipleMode == JNI_TRUE) { |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
277 |
bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
278 |
} else { |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
279 |
bufferLimit = SINGLE_MODE_BUFFER_LIMIT; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
280 |
} |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
281 |
LPTSTR fileBuffer = new TCHAR[bufferLimit]; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
282 |
memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR)); |
2 | 283 |
|
284 |
file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID); |
|
285 |
if (file != NULL) { |
|
286 |
LPCTSTR tmp = JNU_GetStringPlatformChars(env, file, NULL); |
|
9829
59c2c48a4b9e
7012520: Heap overflow vulnerability in FileDialog.show()
dcherepanov
parents:
7668
diff
changeset
|
287 |
_tcsncpy(fileBuffer, tmp, bufferLimit - 2); // the fileBuffer is double null terminated string |
2 | 288 |
JNU_ReleaseStringPlatformChars(env, file, tmp); |
289 |
} else { |
|
290 |
fileBuffer[0] = _T('\0'); |
|
291 |
} |
|
292 |
||
293 |
ofn.lStructSize = sizeof(ofn); |
|
294 |
ofn.lpstrFilter = s_fileFilterString; |
|
295 |
ofn.nFilterIndex = 1; |
|
296 |
/* |
|
297 |
Fix for 6488834. |
|
298 |
To disable Win32 native parent modality we have to set |
|
299 |
hwndOwner field to either NULL or some hidden window. For |
|
300 |
parentless dialogs we use NULL to show them in the taskbar, |
|
301 |
and for all other dialogs AwtToolkit's HWND is used. |
|
302 |
*/ |
|
303 |
if (awtParent != NULL) |
|
304 |
{ |
|
305 |
ofn.hwndOwner = AwtToolkit::GetInstance().GetHWnd(); |
|
306 |
} |
|
307 |
else |
|
308 |
{ |
|
309 |
ofn.hwndOwner = NULL; |
|
310 |
} |
|
311 |
ofn.lpstrFile = fileBuffer; |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
312 |
ofn.nMaxFile = bufferLimit; |
2 | 313 |
ofn.lpstrTitle = titleBuffer; |
314 |
ofn.lpstrInitialDir = directoryBuffer; |
|
315 |
ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | |
|
316 |
OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING; |
|
317 |
fileFilter = env->GetObjectField(peer, |
|
318 |
AwtFileDialog::fileFilterID); |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
319 |
if (!JNU_IsNull(env,fileFilter)) { |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
320 |
ofn.Flags |= OFN_ENABLEINCLUDENOTIFY; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
321 |
} |
2 | 322 |
ofn.lCustData = (LPARAM)peer; |
323 |
ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc; |
|
324 |
||
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
325 |
if (multipleMode == JNI_TRUE) { |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
326 |
ofn.Flags |= OFN_ALLOWMULTISELECT; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
327 |
} |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
328 |
|
2 | 329 |
// Save current directory, so we can reset if it changes. |
330 |
currentDirectory = new TCHAR[MAX_PATH+1]; |
|
331 |
||
332 |
VERIFY(::GetCurrentDirectory(MAX_PATH, currentDirectory) > 0); |
|
333 |
||
334 |
mode = env->GetIntField(target, AwtFileDialog::modeID); |
|
335 |
||
336 |
AwtDialog::CheckInstallModalHook(); |
|
337 |
||
338 |
// show the Win32 file dialog |
|
339 |
if (mode == java_awt_FileDialog_LOAD) { |
|
340 |
result = AwtFileDialog::GetOpenFileName(&ofn); |
|
341 |
} else { |
|
342 |
result = AwtFileDialog::GetSaveFileName(&ofn); |
|
343 |
} |
|
344 |
// Fix for 4181310: FileDialog does not show up. |
|
345 |
// If the dialog is not shown because of invalid file name |
|
346 |
// replace the file name by empty string. |
|
347 |
if (!result) { |
|
1954 | 348 |
dlgerr = ::CommDlgExtendedError(); |
2 | 349 |
if (dlgerr == FNERR_INVALIDFILENAME) { |
350 |
_tcscpy(fileBuffer, TEXT("")); |
|
351 |
if (mode == java_awt_FileDialog_LOAD) { |
|
352 |
result = AwtFileDialog::GetOpenFileName(&ofn); |
|
353 |
} else { |
|
354 |
result = AwtFileDialog::GetSaveFileName(&ofn); |
|
355 |
} |
|
356 |
} |
|
357 |
} |
|
358 |
||
359 |
AwtDialog::CheckUninstallModalHook(); |
|
360 |
||
361 |
DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L); |
|
362 |
||
363 |
AwtDialog::ModalActivateNextWindow(NULL, target, peer); |
|
364 |
||
365 |
VERIFY(::SetCurrentDirectory(currentDirectory)); |
|
366 |
||
367 |
// Report result to peer. |
|
368 |
if (result) { |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
369 |
jint length = (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
370 |
jcharArray jnames = env->NewCharArray(length); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
371 |
env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
372 |
|
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
373 |
env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames); |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
374 |
env->DeleteLocalRef(jnames); |
2 | 375 |
} else { |
376 |
env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID); |
|
377 |
} |
|
378 |
DASSERT(!safe_ExceptionOccurred(env)); |
|
379 |
} catch (...) { |
|
380 |
||
381 |
env->DeleteLocalRef(target); |
|
382 |
env->DeleteLocalRef(parent); |
|
383 |
env->DeleteLocalRef(title); |
|
384 |
env->DeleteLocalRef(directory); |
|
385 |
env->DeleteLocalRef(file); |
|
386 |
env->DeleteLocalRef(fileFilter); |
|
387 |
env->DeleteGlobalRef(peer); |
|
388 |
||
389 |
delete[] currentDirectory; |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
390 |
if (ofn.lpstrFile) |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
391 |
delete[] ofn.lpstrFile; |
2 | 392 |
throw; |
393 |
} |
|
394 |
||
395 |
env->DeleteLocalRef(target); |
|
396 |
env->DeleteLocalRef(parent); |
|
397 |
env->DeleteLocalRef(title); |
|
398 |
env->DeleteLocalRef(directory); |
|
399 |
env->DeleteLocalRef(file); |
|
400 |
env->DeleteLocalRef(fileFilter); |
|
401 |
env->DeleteGlobalRef(peer); |
|
402 |
||
403 |
delete[] currentDirectory; |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
404 |
if (ofn.lpstrFile) |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
405 |
delete[] ofn.lpstrFile; |
2 | 406 |
} |
407 |
||
408 |
BOOL |
|
1954 | 409 |
AwtFileDialog::GetOpenFileName(LPOPENFILENAME data) { |
2 | 410 |
return static_cast<BOOL>(reinterpret_cast<INT_PTR>( |
411 |
AwtToolkit::GetInstance().InvokeFunction((void*(*)(void*)) |
|
1954 | 412 |
::GetOpenFileName, data))); |
2 | 413 |
|
414 |
} |
|
415 |
||
416 |
BOOL |
|
1954 | 417 |
AwtFileDialog::GetSaveFileName(LPOPENFILENAME data) { |
2 | 418 |
return static_cast<BOOL>(reinterpret_cast<INT_PTR>( |
419 |
AwtToolkit::GetInstance().InvokeFunction((void *(*)(void *)) |
|
1954 | 420 |
::GetSaveFileName, data))); |
2 | 421 |
|
422 |
} |
|
423 |
||
424 |
BOOL AwtFileDialog::InheritsNativeMouseWheelBehavior() {return true;} |
|
425 |
||
426 |
void AwtFileDialog::_DisposeOrHide(void *param) |
|
427 |
{ |
|
428 |
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
429 |
||
430 |
jobject self = (jobject)param; |
|
431 |
||
432 |
HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); |
|
433 |
if (::IsWindow(hdlg)) |
|
434 |
{ |
|
435 |
::SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), |
|
436 |
(LPARAM)hdlg); |
|
437 |
} |
|
438 |
||
439 |
env->DeleteGlobalRef(self); |
|
440 |
} |
|
441 |
||
442 |
void AwtFileDialog::_ToFront(void *param) |
|
443 |
{ |
|
444 |
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
445 |
||
446 |
jobject self = (jobject)param; |
|
447 |
HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); |
|
448 |
if (::IsWindow(hdlg)) |
|
449 |
{ |
|
450 |
::SetWindowPos(hdlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); |
|
451 |
} |
|
452 |
||
453 |
env->DeleteGlobalRef(self); |
|
454 |
} |
|
455 |
||
456 |
void AwtFileDialog::_ToBack(void *param) |
|
457 |
{ |
|
458 |
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
|
459 |
||
460 |
jobject self = (jobject)param; |
|
461 |
HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); |
|
462 |
if (::IsWindow(hdlg)) |
|
463 |
{ |
|
464 |
::SetWindowPos(hdlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); |
|
465 |
} |
|
466 |
||
467 |
env->DeleteGlobalRef(self); |
|
468 |
} |
|
469 |
||
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
470 |
// Returns the length of the double null terminated output buffer |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
471 |
UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit) |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
472 |
{ |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
473 |
UINT index = 0; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
474 |
while ((index < limit) && |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
475 |
(buffer[index] != NULL || buffer[index+1] != NULL)) |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
476 |
{ |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
477 |
index++; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
478 |
} |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
479 |
return index; |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
480 |
} |
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
481 |
|
2 | 482 |
/************************************************************************ |
483 |
* WFileDialogPeer native methods |
|
484 |
*/ |
|
485 |
||
486 |
extern "C" { |
|
487 |
||
488 |
JNIEXPORT void JNICALL |
|
489 |
Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv *env, jclass cls) |
|
490 |
{ |
|
491 |
TRY; |
|
492 |
||
493 |
AwtFileDialog::parentID = |
|
494 |
env->GetFieldID(cls, "parent", "Lsun/awt/windows/WComponentPeer;"); |
|
495 |
AwtFileDialog::fileFilterID = |
|
496 |
env->GetFieldID(cls, "fileFilter", "Ljava/io/FilenameFilter;"); |
|
497 |
AwtFileDialog::setHWndMID = |
|
498 |
env->GetMethodID(cls, "setHWnd", "(J)V"); |
|
499 |
AwtFileDialog::handleSelectedMID = |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
500 |
env->GetMethodID(cls, "handleSelected", "([C)V"); |
2 | 501 |
AwtFileDialog::handleCancelMID = |
502 |
env->GetMethodID(cls, "handleCancel", "()V"); |
|
503 |
AwtFileDialog::checkFilenameFilterMID = |
|
504 |
env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z"); |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
505 |
AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z"); |
2 | 506 |
|
507 |
/* java.awt.FileDialog fields */ |
|
508 |
cls = env->FindClass("java/awt/FileDialog"); |
|
509 |
if (cls == NULL) { |
|
510 |
return; |
|
511 |
} |
|
512 |
AwtFileDialog::modeID = env->GetFieldID(cls, "mode", "I"); |
|
513 |
AwtFileDialog::dirID = env->GetFieldID(cls, "dir", "Ljava/lang/String;"); |
|
514 |
AwtFileDialog::fileID = env->GetFieldID(cls, "file", "Ljava/lang/String;"); |
|
515 |
AwtFileDialog::filterID = |
|
516 |
env->GetFieldID(cls, "filter", "Ljava/io/FilenameFilter;"); |
|
517 |
||
518 |
DASSERT(AwtFileDialog::parentID != NULL); |
|
519 |
DASSERT(AwtFileDialog::setHWndMID != NULL); |
|
520 |
DASSERT(AwtFileDialog::handleSelectedMID != NULL); |
|
521 |
DASSERT(AwtFileDialog::handleCancelMID != NULL); |
|
4913
9b3caa50afcf
6705345: Enable multiple file selection in AWT FileDialog
dcherepanov
parents:
2456
diff
changeset
|
522 |
DASSERT(AwtFileDialog::isMultipleModeMID != NULL); |
2 | 523 |
|
524 |
DASSERT(AwtFileDialog::modeID != NULL); |
|
525 |
DASSERT(AwtFileDialog::dirID != NULL); |
|
526 |
DASSERT(AwtFileDialog::fileID != NULL); |
|
527 |
DASSERT(AwtFileDialog::filterID != NULL); |
|
528 |
||
529 |
CATCH_BAD_ALLOC; |
|
530 |
} |
|
531 |
||
532 |
JNIEXPORT void JNICALL |
|
533 |
Java_sun_awt_windows_WFileDialogPeer_setFilterString(JNIEnv *env, jclass cls, |
|
534 |
jstring filterDescription) |
|
535 |
{ |
|
536 |
TRY; |
|
537 |
||
538 |
AwtFileDialog::Initialize(env, filterDescription); |
|
539 |
||
540 |
CATCH_BAD_ALLOC; |
|
541 |
} |
|
542 |
||
543 |
JNIEXPORT void JNICALL |
|
544 |
Java_sun_awt_windows_WFileDialogPeer__1show(JNIEnv *env, jobject peer) |
|
545 |
{ |
|
546 |
TRY; |
|
547 |
||
548 |
/* |
|
549 |
* Fix for 4906972. |
|
550 |
* 'peer' reference has to be global as it's used further in another thread. |
|
551 |
*/ |
|
552 |
jobject peerGlobal = env->NewGlobalRef(peer); |
|
553 |
||
554 |
AwtToolkit::GetInstance().InvokeFunction(AwtFileDialog::Show, peerGlobal); |
|
555 |
||
556 |
env->DeleteGlobalRef(peerGlobal); |
|
557 |
||
558 |
CATCH_BAD_ALLOC; |
|
559 |
} |
|
560 |
||
561 |
JNIEXPORT void JNICALL |
|
562 |
Java_sun_awt_windows_WFileDialogPeer__1dispose(JNIEnv *env, jobject peer) |
|
563 |
{ |
|
564 |
TRY_NO_VERIFY; |
|
565 |
||
566 |
jobject peerGlobal = env->NewGlobalRef(peer); |
|
567 |
||
568 |
AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide, |
|
569 |
(void *)peerGlobal); |
|
570 |
// peerGlobal ref is deleted in _DisposeOrHide |
|
571 |
||
572 |
CATCH_BAD_ALLOC; |
|
573 |
} |
|
574 |
||
575 |
JNIEXPORT void JNICALL |
|
576 |
Java_sun_awt_windows_WFileDialogPeer__1hide(JNIEnv *env, jobject peer) |
|
577 |
{ |
|
578 |
TRY; |
|
579 |
||
580 |
jobject peerGlobal = env->NewGlobalRef(peer); |
|
581 |
||
582 |
AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide, |
|
583 |
(void *)peerGlobal); |
|
584 |
// peerGlobal ref is deleted in _DisposeOrHide |
|
585 |
||
586 |
CATCH_BAD_ALLOC; |
|
587 |
} |
|
588 |
||
589 |
JNIEXPORT void JNICALL |
|
590 |
Java_sun_awt_windows_WFileDialogPeer_toFront(JNIEnv *env, jobject peer) |
|
591 |
{ |
|
592 |
TRY; |
|
593 |
||
594 |
AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToFront, |
|
595 |
(void *)(env->NewGlobalRef(peer))); |
|
596 |
// global ref is deleted in _ToFront |
|
597 |
||
598 |
CATCH_BAD_ALLOC; |
|
599 |
} |
|
600 |
||
601 |
JNIEXPORT void JNICALL |
|
602 |
Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv *env, jobject peer) |
|
603 |
{ |
|
604 |
TRY; |
|
605 |
||
606 |
AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_ToBack, |
|
607 |
(void *)(env->NewGlobalRef(peer))); |
|
608 |
// global ref is deleted in _ToBack |
|
609 |
||
610 |
CATCH_BAD_ALLOC; |
|
611 |
} |
|
612 |
||
613 |
} /* extern "C" */ |