diff options
| -rw-r--r-- | src/Fl_Native_File_Chooser_WIN32.cxx | 94 | ||||
| -rw-r--r-- | test/native-filechooser.cxx | 18 |
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()); } |
