--- a/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp Mon Feb 08 17:02:43 2010 +0300
+++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp Fri Feb 12 19:58:10 2010 +0300
@@ -44,6 +44,7 @@
jmethodID AwtFileDialog::handleSelectedMID;
jmethodID AwtFileDialog::handleCancelMID;
jmethodID AwtFileDialog::checkFilenameFilterMID;
+jmethodID AwtFileDialog::isMultipleModeMID;
/* FileDialog ids */
jfieldID AwtFileDialog::modeID;
@@ -57,6 +58,13 @@
/* Non-localized suffix of the filter string */
static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0");
+// Default limit of the output buffer.
+#define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1
+#define MULTIPLE_MODE_BUFFER_LIMIT 32768
+
+// The name of the property holding the pointer to the OPENFILENAME structure.
+static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN");
+
/***********************************************************************/
void
@@ -140,6 +148,8 @@
FileDialogWndProc);
::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc));
+ ::SetProp(parent, OpenFileNameProp, (void *)lParam);
+
break;
}
case WM_DESTROY: {
@@ -149,6 +159,7 @@
lpfnWndProc);
::RemoveProp(parent, ModalDialogPeerProp);
::RemoveProp(parent, NativeDialogWndProcProp);
+ ::RemoveProp(parent, OpenFileNameProp);
break;
}
case WM_NOTIFY: {
@@ -174,6 +185,30 @@
// to unblock all the windows blocked by this dialog as it will
// be closed soon
env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0);
+ } else if (notifyEx->hdr.code == CDN_SELCHANGE) {
+ // reallocate the buffer if the buffer is too small
+ LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp);
+
+ UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) +
+ CommDlg_OpenSave_GetFolderPath(parent, NULL, 0);
+
+ if (lpofn->nMaxFile < nLength)
+ {
+ // allocate new buffer
+ LPTSTR newBuffer = new TCHAR[nLength];
+
+ if (newBuffer) {
+ memset(newBuffer, 0, nLength * sizeof(TCHAR));
+ LPTSTR oldBuffer = lpofn->lpstrFile;
+ lpofn->lpstrFile = newBuffer;
+ lpofn->nMaxFile = nLength;
+ // free the previously allocated buffer
+ if (oldBuffer) {
+ delete[] oldBuffer;
+ }
+
+ }
+ }
}
}
break;
@@ -193,7 +228,6 @@
WCHAR unicodeChar = L' ';
LPTSTR fileBuffer = NULL;
LPTSTR currentDirectory = NULL;
- OPENFILENAME ofn;
jint mode = 0;
BOOL result = FALSE;
DWORD dlgerr;
@@ -204,6 +238,10 @@
jobject target = NULL;
jobject parent = NULL;
AwtComponent* awtParent = NULL;
+ jboolean multipleMode = JNI_FALSE;
+
+ OPENFILENAME ofn;
+ memset(&ofn, 0, sizeof(ofn));
/*
* There's a situation (see bug 4906972) when InvokeFunction (by which this method is called)
@@ -233,7 +271,16 @@
(jstring)env->GetObjectField(target, AwtFileDialog::dirID);
JavaStringBuffer directoryBuffer(env, directory);
- fileBuffer = new TCHAR[MAX_PATH+1];
+ multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID);
+
+ UINT bufferLimit;
+ if (multipleMode == JNI_TRUE) {
+ bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT;
+ } else {
+ bufferLimit = SINGLE_MODE_BUFFER_LIMIT;
+ }
+ LPTSTR fileBuffer = new TCHAR[bufferLimit];
+ memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR));
file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID);
if (file != NULL) {
@@ -244,8 +291,6 @@
fileBuffer[0] = _T('\0');
}
- memset(&ofn, 0, sizeof(ofn));
-
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFilter = s_fileFilterString;
ofn.nFilterIndex = 1;
@@ -265,19 +310,23 @@
ofn.hwndOwner = NULL;
}
ofn.lpstrFile = fileBuffer;
- ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFile = bufferLimit;
ofn.lpstrTitle = titleBuffer;
ofn.lpstrInitialDir = directoryBuffer;
ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING;
fileFilter = env->GetObjectField(peer,
AwtFileDialog::fileFilterID);
- if (!JNU_IsNull(env,fileFilter)) {
- ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
- }
+ if (!JNU_IsNull(env,fileFilter)) {
+ ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
+ }
ofn.lCustData = (LPARAM)peer;
ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc;
+ if (multipleMode == JNI_TRUE) {
+ ofn.Flags |= OFN_ALLOWMULTISELECT;
+ }
+
// Save current directory, so we can reset if it changes.
currentDirectory = new TCHAR[MAX_PATH+1];
@@ -318,11 +367,12 @@
// Report result to peer.
if (result) {
- jstring tmpJString = (_tcslen(ofn.lpstrFile) == 0 ?
- JNU_NewStringPlatform(env, L"") :
- JNU_NewStringPlatform(env, ofn.lpstrFile));
- env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, tmpJString);
- env->DeleteLocalRef(tmpJString);
+ jint length = (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile);
+ jcharArray jnames = env->NewCharArray(length);
+ env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile);
+
+ env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames);
+ env->DeleteLocalRef(jnames);
} else {
env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID);
}
@@ -338,7 +388,8 @@
env->DeleteGlobalRef(peer);
delete[] currentDirectory;
- delete[] fileBuffer;
+ if (ofn.lpstrFile)
+ delete[] ofn.lpstrFile;
throw;
}
@@ -351,7 +402,8 @@
env->DeleteGlobalRef(peer);
delete[] currentDirectory;
- delete[] fileBuffer;
+ if (ofn.lpstrFile)
+ delete[] ofn.lpstrFile;
}
BOOL
@@ -416,6 +468,18 @@
env->DeleteGlobalRef(self);
}
+// Returns the length of the double null terminated output buffer
+UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit)
+{
+ UINT index = 0;
+ while ((index < limit) &&
+ (buffer[index] != NULL || buffer[index+1] != NULL))
+ {
+ index++;
+ }
+ return index;
+}
+
/************************************************************************
* WFileDialogPeer native methods
*/
@@ -434,11 +498,12 @@
AwtFileDialog::setHWndMID =
env->GetMethodID(cls, "setHWnd", "(J)V");
AwtFileDialog::handleSelectedMID =
- env->GetMethodID(cls, "handleSelected", "(Ljava/lang/String;)V");
+ env->GetMethodID(cls, "handleSelected", "([C)V");
AwtFileDialog::handleCancelMID =
env->GetMethodID(cls, "handleCancel", "()V");
AwtFileDialog::checkFilenameFilterMID =
env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z");
+ AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z");
/* java.awt.FileDialog fields */
cls = env->FindClass("java/awt/FileDialog");
@@ -455,6 +520,7 @@
DASSERT(AwtFileDialog::setHWndMID != NULL);
DASSERT(AwtFileDialog::handleSelectedMID != NULL);
DASSERT(AwtFileDialog::handleCancelMID != NULL);
+ DASSERT(AwtFileDialog::isMultipleModeMID != NULL);
DASSERT(AwtFileDialog::modeID != NULL);
DASSERT(AwtFileDialog::dirID != NULL);