Allow unix style paths for windows native filechooser
Allows and preserves unix style paths if user specifies them, otherwise uses Windows style. This allows end users to use either style path and get behavior they expect in cross-platform environments. Addresses problems raised by issue #122
This commit is contained in:
parent
b105dd726f
commit
0da41da713
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user