summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Fl_Native_File_Chooser_WIN32.cxx94
-rw-r--r--test/native-filechooser.cxx18
2 files changed, 82 insertions, 30 deletions
diff --git a/src/Fl_Native_File_Chooser_WIN32.cxx b/src/Fl_Native_File_Chooser_WIN32.cxx
index 580e6e23a..4b982a697 100644
--- a/src/Fl_Native_File_Chooser_WIN32.cxx
+++ b/src/Fl_Native_File_Chooser_WIN32.cxx
@@ -29,6 +29,7 @@
#define FNFC_MAX_PATH 32768 // XXX: MAX_PATH under win32 is 260, too small for modern use
+#include <FL/fl_string.h> // fl_strdup()
#include <FL/Fl_Native_File_Chooser.H>
# include <windows.h>
# include <commdlg.h> // OPENFILENAMEW, GetOpenFileName()
@@ -65,6 +66,7 @@ private:
void ClearBINF();
void Win2Unix(char *s);
void Unix2Win(char *s);
+ bool IsUnixPath(const char *s);
int showfile();
int showdir();
@@ -338,14 +340,24 @@ void Fl_WinAPI_Native_File_Chooser_Driver::ClearBINF() {
// CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES
void Fl_WinAPI_Native_File_Chooser_Driver::Win2Unix(char *s) {
- for ( ; *s; s++ )
- if ( *s == '\\' ) *s = '/';
+ while ( s=strchr(s,'\\') ) *s = '/';
}
// CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES
void Fl_WinAPI_Native_File_Chooser_Driver::Unix2Win(char *s) {
- for ( ; *s; s++ )
- if ( *s == '/' ) *s = '\\';
+ while ( s=strchr(s,'/') ) *s = '\\';
+}
+
+// SEE IF PATH IS FRONT SLASH OR BACKSLASH STYLE
+// Use this to preserve path style after windows dialog appears.
+// If no slashes are specified, windows is assumed.
+// If a mix of both path styles is used, windows is assumed.
+//
+bool Fl_WinAPI_Native_File_Chooser_Driver::IsUnixPath(const char *s) {
+ if ( !s ) return false; // NULL?
+ if ( strchr(s, '\\') ) return false; // windows style?
+ if ( strchr(s, '/') ) return true; // unix style?
+ return false; // no slashes? assume native windows
}
// SAVE THE CURRENT WORKING DIRECTORY
@@ -375,6 +387,7 @@ static void RestoreCWD(char *thecwd) {
// SHOW FILE BROWSER
int Fl_WinAPI_Native_File_Chooser_Driver::showfile() {
+ bool unixpath = IsUnixPath(_directory) | IsUnixPath(_preset_file); // caller uses unix paths?
ClearOFN();
clear_pathnames();
size_t fsize = FNFC_MAX_PATH;
@@ -403,7 +416,7 @@ int Fl_WinAPI_Native_File_Chooser_Driver::showfile() {
}
// SPACE FOR RETURNED FILENAME
_ofn_ptr->lpstrFile = new WCHAR[fsize];
- _ofn_ptr->nMaxFile = (DWORD) fsize-1;
+ _ofn_ptr->nMaxFile = (DWORD)(fsize-1);
_ofn_ptr->lpstrFile[0] = 0;
_ofn_ptr->lpstrFile[1] = 0; // dnull
// PARENT WINDOW
@@ -434,27 +447,40 @@ int Fl_WinAPI_Native_File_Chooser_Driver::showfile() {
// XXX: this doesn't preselect the item in the listview.. why?
//
if ( _preset_file ) {
- size_t len = strlen(_preset_file);
+ // Temp copy of _dirname we can convert to windows path if needed
+ char *winpath = fl_strdup(_preset_file);
+ if ( unixpath ) Unix2Win(winpath);
+ size_t len = strlen(winpath);
if ( len >= _ofn_ptr->nMaxFile ) {
char msg[80];
sprintf(msg, "preset_file() filename is too long: %ld is >=%ld", (long)len, (long)fsize);
errmsg(msg);
return(-1);
}
- wcscpy(_ofn_ptr->lpstrFile, utf8towchar(_preset_file));
- // Unix2Win(_ofn_ptr->lpstrFile);
+ wcscpy(_ofn_ptr->lpstrFile, utf8towchar(winpath));
len = wcslen(_ofn_ptr->lpstrFile);
_ofn_ptr->lpstrFile[len+0] = 0; // multiselect needs dnull
_ofn_ptr->lpstrFile[len+1] = 0;
+ free(winpath); // free temp copy now that we have a new wchar
+ //wprintf(L"lpstrFile is '%ls'\n", (WCHAR*)(_ofn_ptr->lpstrFile));
}
+ // PRESET DIR
+ // XXX: See KB Q86920 for doc bug:
+ // http://support.microsoft.com/default.aspx?scid=kb;en-us;86920
+ //
if ( _directory ) {
- // PRESET DIR
- // XXX: See KB Q86920 for doc bug:
- // http://support.microsoft.com/default.aspx?scid=kb;en-us;86920
+ // Temp copy of _dirname we can convert to windows path if needed
+ char *winpath = fl_strdup(_directory);
+ // Caller specified unix front slash path?
+ // If so, convert to backslashes; windows native browser mishandles unix style paths.
+ // We'll convert back to unix style when dialog completes.
//
- _ofn_ptr->lpstrInitialDir = new WCHAR[FNFC_MAX_PATH];
- wcscpy((WCHAR *)_ofn_ptr->lpstrInitialDir, utf8towchar(_directory));
- // Unix2Win((char*)_ofn_ptr->lpstrInitialDir);
+ if ( unixpath ) Unix2Win(winpath);
+ // Make a wide char version of potentially utf8 string
+ _ofn_ptr->lpstrInitialDir = new WCHAR[FNFC_MAX_PATH];
+ wcscpy((WCHAR *)_ofn_ptr->lpstrInitialDir, utf8towchar(winpath));
+ free(winpath); // free temp copy now that we have a new wchar
+ //wprintf(L"lpstrInitialDir is '%ls'\n", (WCHAR*)(_ofn_ptr->lpstrInitialDir));
}
// SAVE THE CURRENT DIRECTORY
// See above warning (XXX) for OFN_NOCHANGEDIR
@@ -485,7 +511,7 @@ int Fl_WinAPI_Native_File_Chooser_Driver::showfile() {
case Fl_Native_File_Chooser::BROWSE_FILE:
case Fl_Native_File_Chooser::BROWSE_SAVE_FILE:
set_single_pathname(wchartoutf8(_ofn_ptr->lpstrFile));
- // Win2Unix(_pathnames[_tpathnames-1]);
+ if ( unixpath ) Win2Unix(_pathnames[_tpathnames-1]); // preserve unix style path
break;
case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: {
// EXTRACT MULTIPLE FILENAMES
@@ -497,11 +523,12 @@ int Fl_WinAPI_Native_File_Chooser_Driver::showfile() {
//
char pathname[FNFC_MAX_PATH];
for ( const WCHAR *s = dirname + dirlen + 1;
- *s; s+= (wcslen(s)+1)) {
- strcpy(pathname, wchartoutf8(dirname));
- strcat(pathname, "\\");
- strcat(pathname, wchartoutf8(s));
- add_pathname(pathname);
+ *s; s += (wcslen(s)+1)) {
+ strncpy(pathname, wchartoutf8(dirname), FNFC_MAX_PATH);
+ strncat(pathname, "\\", FNFC_MAX_PATH);
+ strncat(pathname, wchartoutf8(s), FNFC_MAX_PATH);
+ pathname[FNFC_MAX_PATH-1] = 0;
+ add_pathname(pathname);
}
}
// XXX
@@ -511,7 +538,12 @@ int Fl_WinAPI_Native_File_Chooser_Driver::showfile() {
//
if ( _tpathnames == 0 ) {
add_pathname(wchartoutf8(dirname));
- // Win2Unix(_pathnames[_tpathnames-1]);
+ }
+ // Caller specified unix path? Return unix paths
+ if ( unixpath ) {
+ for ( int t=0; t<_tpathnames; t++ ) {
+ Win2Unix(_pathnames[t]);
+ }
}
break;
}
@@ -553,6 +585,7 @@ static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data) {
// SHOW DIRECTORY BROWSER
int Fl_WinAPI_Native_File_Chooser_Driver::showdir() {
+ bool unixpath = IsUnixPath(_directory); // caller uses unix paths?
// initialize OLE only once
fl_open_display(); // init needed by BIF_USENEWUI
ClearBINF();
@@ -609,10 +642,20 @@ int Fl_WinAPI_Native_File_Chooser_Driver::showdir() {
// PRESET DIR
WCHAR presetname[FNFC_MAX_PATH];
if ( _directory ) {
- // Unix2Win(presetname);
- wcsncpy(presetname, utf8towchar(_directory), FNFC_MAX_PATH);
- presetname[FNFC_MAX_PATH-1] = 0;
+ // Temp copy of _dirname we can convert to windows path if needed
+ char *winpath = fl_strdup(_directory);
+ // Caller specified unix front slash path?
+ // If so, convert to backslashes; windows native browser mishandles unix style paths.
+ // We'll convert back to unix style when dialog completes.
+ //
+ if ( unixpath ) Unix2Win(winpath);
+ // Wide char version of potentially utf8 string
+ wcsncpy(presetname, utf8towchar(winpath), FNFC_MAX_PATH);
+ free(winpath); // free temp copy now that we have a new wchar
+ presetname[FNFC_MAX_PATH-1] = 0; // dnull
+ presetname[FNFC_MAX_PATH-2] = 0;
_binf_ptr->lParam = (LPARAM)presetname;
+ //wprintf(L"presetname is '%ls'\n", (WCHAR*)(presetname));
}
else _binf_ptr->lParam = 0;
_binf_ptr->lpfn = Dir_CB;
@@ -627,9 +670,8 @@ int Fl_WinAPI_Native_File_Chooser_Driver::showdir() {
WCHAR path[FNFC_MAX_PATH];
if ( SHGetPathFromIDListW(pidl, path) ) {
- // Win2Unix(path);
- //add_pathname(path);
add_pathname(wchartoutf8(path));
+ if ( unixpath ) Win2Unix(_pathnames[_tpathnames-1]); // preserve unix style path
}
FreePIDL(pidl);
if ( !wcslen(path) ) return(1); // don't return empty pathnames
diff --git a/test/native-filechooser.cxx b/test/native-filechooser.cxx
index dd0c4812d..df2433021 100644
--- a/test/native-filechooser.cxx
+++ b/test/native-filechooser.cxx
@@ -93,10 +93,15 @@ int main(int argc, char **argv) {
int argn = 1;
#ifdef __APPLE__
// OS X may add the process number as the first argument - ignore
- if (argc>argn && strncmp(argv[1], "-psn_", 5)==0)
- argn++;
+ if (argc>argn && strncmp(argv[argn], "-psn_", 5)==0) ++argn;
#endif
+ // Parse preset filename (if any)
+ char *filename = 0;
+ if ( argc>argn && argv[argn][0] != '-' ) {
+ filename = argv[argn++];
+ }
+
Fl_Window *win = new Fl_Window(640, 400+TERMINAL_HEIGHT, "Native File Chooser Test");
win->size_range(win->w(), win->h(), 0, 0);
win->begin();
@@ -105,7 +110,7 @@ int main(int argc, char **argv) {
int x = 80, y = 10;
G_filename = new Fl_Input(x, y, win->w()-80-10, 25, "Filename");
- G_filename->value(argc <= argn ? "." : argv[argn]);
+ G_filename->value(filename ? filename : ".");
G_filename->tooltip("Default filename");
y += G_filename->h() + 10;
@@ -148,6 +153,11 @@ int main(int argc, char **argv) {
win->resizable(G_filter);
}
win->end();
- win->show(argc, argv);
+ // Pass show() remaining args we haven't already parsed..
+ {
+ char **args = argv+(argn-1);
+ int nargs = argc-(argn-1);
+ win->show(nargs, args);
+ }
return(Fl::run());
}