Files
tlib/oversampling/WDL/filebrowse.cpp
2024-05-24 13:28:31 +02:00

494 lines
13 KiB
C++

// todo: support win7/vista extensions rather than GetOpenFileName? -- merge win7filedialog into here.
#include "filebrowse.h"
#include "win32_utf8.h"
#include "wdlcstring.h"
#ifdef _WIN32
#ifdef _MSC_VER // todo: win7filedialog.cpp support for mingw32
#define WDL_FILEBROWSE_WIN7VISTAMODE
#endif
#endif
#ifdef WDL_FILEBROWSE_WIN7VISTAMODE // win7/vista file dialog support
#include "win7filedialog.cpp"
// stuff since win7filedialog.h collides with shlobj.h below
#define tagSHCONTF tagSHCONTF___
#define SHCONTF SHCONTF___
#define SHCONTF_FOLDERS SHCONTF_FOLDERS___
#define SHCONTF_NONFOLDERS SHCONTF_NONFOLDERS___
#define SHCONTF_INCLUDEHIDDEN SHCONTF_INCLUDEHIDDEN___
#define SHCONTF_SHAREABLE SHCONTF_SHAREABLE__
#define SHCONTF_INIT_ON_FIRST_NEXT SHCONTF_INIT_ON_FIRST_NEXT__
#define SHCONTF_NETPRINTERSRCH SHCONTF_NETPRINTERSRCH__
#define SHCONTF_STORAGE SHCONTF_STORAGE__
#endif
#ifdef _WIN32
// include after win7filedialog.*
#include <commctrl.h>
#include <shlobj.h>
#endif
#ifndef BIF_NEWDIALOGSTYLE
#define BIF_NEWDIALOGSTYLE 0x40
#endif
static void WDL_fixfnforopenfn(char *buf)
{
char *p=buf;
while (*p)
{
if (WDL_IS_DIRCHAR(*p)) *p = WDL_DIRCHAR;
p++;
}
#ifdef _WIN32
if (buf[0] && buf[1] == ':')
{
p=buf+2;
char *op=p;
while (*p)
{
while (p[0]==WDL_DIRCHAR && p[1] == WDL_DIRCHAR) p++;
*op++ = *p++;
}
*op=0;
}
#endif
}
#ifdef _WIN32
static int CALLBACK WINAPI WDL_BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
switch (uMsg)
{
case BFFM_INITIALIZED:
{
if (lpData && ((char *)lpData)[0])
{
#ifndef WDL_NO_SUPPORT_UTF8
WDL_UTF8_SendBFFM_SETSEL(hwnd, (const char *)lpData);
#else
SendMessage(hwnd, BFFM_SETSELECTION, 1, lpData);
#endif
}
break;
}
}
return 0;
}
#endif
bool WDL_ChooseDirectory(HWND parent, const char *text, const char *initialdir, char *fn, int fnsize, bool preservecwd)
{
char olddir[2048];
GetCurrentDirectory(sizeof(olddir),olddir);
#ifdef _WIN32
char name[4096];
lstrcpyn_safe(name,initialdir?initialdir:"",sizeof(name));
BROWSEINFO bi={parent,NULL, name, text, BIF_RETURNONLYFSDIRS|BIF_NEWDIALOGSTYLE, WDL_BrowseCallbackProc, (LPARAM)name,};
LPITEMIDLIST idlist = SHBrowseForFolderUTF8( &bi );
if (idlist && SHGetPathFromIDListUTF8(idlist, name, sizeof(name)))
{
IMalloc *m;
SHGetMalloc(&m);
m->Free(idlist);
lstrcpyn_safe(fn,name,fnsize);
return true;
}
return false;
#else
bool r = BrowseForDirectory(text,initialdir,fn,fnsize);
if (preservecwd) SetCurrentDirectory(olddir);
return r;
#endif
}
#ifdef _WIN32
struct WDL_FileBrowse_Dis {
enum { DLSZ = 10 };
WDL_FileBrowse_Dis(HWND par)
{
m_par = par;
memset(m_dislist,0,sizeof(m_dislist));
if (par) EnableOwnerWnds(par,0);
}
~WDL_FileBrowse_Dis()
{
if (m_dislist[0]) EnableOwnerWnds(m_par, 1);
}
void EnableOwnerWnds(HWND p, int en)
{
int limit = 0, dlsz = 0;
HWND t;
while (NULL != (t = GetParent(p)) && limit++ < 20)
{
p = t;
if (!(GetWindowLong(p,GWL_STYLE)&WS_CHILD) && !en != !IsWindowEnabled(p))
{
if (!en)
{
EnableWindow(p,0);
m_dislist[dlsz] = p;
if (++dlsz == DLSZ) break;
}
else
{
for (dlsz = 0; dlsz < DLSZ && m_dislist[dlsz] != p && m_dislist[dlsz]; dlsz++);
if (dlsz < DLSZ && m_dislist[dlsz] == p) EnableWindow(p,1);
}
}
}
}
HWND m_par, m_dislist[DLSZ];
};
#endif
#ifdef _WIN32
bool wdl_use_legacy_filebrowse;
#endif
bool WDL_ChooseFileForSave(HWND parent,
const char *text,
const char *initialdir,
const char *initialfile,
const char *extlist,
const char *defext,
bool preservecwd,
char *fn,
int fnsize,
const char *dlgid,
void *dlgProc,
#ifdef _WIN32
HINSTANCE hInstance
#else
struct SWELL_DialogResourceIndex *reshead
#endif
)
{
char cwd[2048];
GetCurrentDirectory(sizeof(cwd),cwd);
while (defext && *defext == '.') defext++; // this function can be passed defext of either .wav or wav, we always want it to be the latter
#ifdef _WIN32
WDL_FileBrowse_Dis win32disfix(parent);
char temp[4096];
memset(temp,0,sizeof(temp));
if (initialfile) lstrcpyn_safe(temp,initialfile,sizeof(temp));
WDL_fixfnforopenfn(temp);
#ifdef WDL_FILEBROWSE_WIN7VISTAMODE
if (!wdl_use_legacy_filebrowse)
{
Win7FileDialog fd(text, 1);
if(fd.inited())
{
fd.addOptions(FOS_DONTADDTORECENT);
//vista+ file open dialog
char olddir[2048];
GetCurrentDirectory(sizeof(olddir),olddir);
fd.setFilterList(extlist);
if (defext)
{
fd.setDefaultExtension(defext);
int i = 0;
const char *p = extlist;
while(*p)
{
if(*p) p+=strlen(p)+1;
if(!*p) break;
const char *ext = WDL_get_fileext(p);
if (*ext == '.') ext++;
if(!stricmp(ext,defext))
{
fd.setFileTypeIndex(i+1);
break;
}
i++;
p+=strlen(p)+1;
}
}
fd.setFolder(initialdir?initialdir:olddir, 0);
if(initialfile)
{
//check for folder name
if (WDL_remove_filepart(temp))
{
//folder found
fd.setFolder(temp, 0);
fd.setFilename(temp + strlen(temp) + 1);
}
else
fd.setFilename(*temp ? temp : initialfile);
}
fd.setTemplate(hInstance, dlgid, (LPOFNHOOKPROC)dlgProc);
if(fd.show(parent))
{
//ifilesavedialog saves the last folder automatically
fd.getResult(fn, fnsize);
if (preservecwd) SetCurrentDirectory(olddir);
return true;
}
if (preservecwd) SetCurrentDirectory(olddir);
return NULL;
}
}
#endif
OPENFILENAME l={sizeof(l),parent, hInstance, extlist, NULL,0, 0, temp, sizeof(temp)-1, NULL, 0, initialdir&&initialdir[0] ? initialdir : cwd, text,
OFN_HIDEREADONLY|OFN_EXPLORER|OFN_OVERWRITEPROMPT,0,0,defext, 0, (LPOFNHOOKPROC)dlgProc, dlgid};
if (hInstance&&dlgProc&&dlgid) l.Flags |= OFN_ENABLEHOOK|OFN_ENABLETEMPLATE|OFN_ENABLESIZING;
if (preservecwd) l.Flags |= OFN_NOCHANGEDIR;
if (!GetSaveFileName(&l)||!temp[0])
{
if (preservecwd) SetCurrentDirectory(cwd);
return false;
}
if (preservecwd) SetCurrentDirectory(cwd);
lstrcpyn_safe(fn,temp,fnsize);
return true;
#else
BrowseFile_SetTemplate(dlgid,(DLGPROC)dlgProc,reshead);
char if_temp[4096];
if (initialfile && *initialfile)
{
lstrcpyn_safe(if_temp,initialfile,sizeof(if_temp));
WDL_fixfnforopenfn(if_temp);
initialfile = if_temp;
}
else
{
if (defext && *defext)
{
snprintf(if_temp,sizeof(if_temp),".%s",defext); // SWELL treats initialfile of ".ext" as default extension
initialfile = if_temp;
}
}
bool r = BrowseForSaveFile(text,initialdir,initialfile,extlist,fn,fnsize);
if (preservecwd) SetCurrentDirectory(cwd);
return r;
#endif
}
char *WDL_ChooseFileForOpen2(HWND parent,
const char *text,
const char *initialdir,
const char *initialfile,
const char *extlist,
const char *defext,
bool preservecwd,
int allowmul,
const char *dlgid,
void *dlgProc,
#ifdef _WIN32
HINSTANCE hInstance
#else
struct SWELL_DialogResourceIndex *reshead
#endif
)
{
char olddir[2048];
GetCurrentDirectory(sizeof(olddir),olddir);
#ifdef _WIN32
WDL_FileBrowse_Dis win32disfix(parent);
#ifdef WDL_FILEBROWSE_WIN7VISTAMODE
if (!wdl_use_legacy_filebrowse && allowmul!=1)
{
Win7FileDialog fd(text);
if(fd.inited())
{
//vista+ file open dialog
fd.addOptions(FOS_FILEMUSTEXIST|(allowmul?FOS_ALLOWMULTISELECT:0));
fd.setFilterList(extlist);
if (defext)
{
fd.setDefaultExtension(defext);
int i = 0;
const char *p = extlist;
while(*p)
{
if(*p) p+=strlen(p)+1;
if(!*p) break;
if(WDL_stristr(p, defext))
{
fd.setFileTypeIndex(i+1);
break;
}
i++;
p+=strlen(p)+1;
}
}
fd.setFolder(initialdir?initialdir:olddir, 0);
fd.setTemplate(hInstance, dlgid, (LPOFNHOOKPROC)dlgProc);
if(initialfile)
{
char temp[4096];
lstrcpyn_safe(temp,initialfile,sizeof(temp));
WDL_fixfnforopenfn(temp);
//check for folder name
if (WDL_remove_filepart(temp))
{
//folder found
fd.setFolder(temp, 0);
fd.setFilename(temp + strlen(temp) + 1);
}
else
fd.setFilename(temp);
}
if(fd.show(parent))
{
char *ret=NULL;
char temp[4096];
temp[0]=0;
//ifileopendialog saves the last folder automatically
if (!allowmul)
{
fd.getResult(temp, sizeof(temp)-1);
ret= temp[0] ? strdup(temp) : NULL;
}
else
{
char* p=NULL;
int totallen=0, cnt=fd.getResultCount();
if (cnt>1)
{
// sets an empty path as 1st returned string for multipath support
// (when selecting files among search results for ex.)
ret = strdup("");
totallen=1;
}
int i;
for (i=0; i<cnt; i++)
{
int len = fd.getResult(i, temp, sizeof(temp)-1);
p = len ? (char*)realloc(ret, totallen + len + ((i==cnt-1)?1:0)) : NULL;
if (p)
{
ret=p;
memcpy(ret+totallen, temp, len);
totallen+=len;
}
else
{
free(ret);
ret=NULL;
break;
}
}
if (ret) p[totallen]=0;
}
if (preservecwd) SetCurrentDirectory(olddir);
return ret;
}
if (preservecwd) SetCurrentDirectory(olddir);
return NULL;
}
}
#endif
int temp_size = allowmul ? 256*1024-1 : 4096-1;
char *temp = (char *)calloc(temp_size+1,1);
OPENFILENAME l={sizeof(l), parent, hInstance, extlist, NULL, 0, 0, temp, temp_size, NULL, 0, initialdir, text,
OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST,0,0, (char *)(defext ? defext : ""), 0, (LPOFNHOOKPROC)dlgProc, dlgid};
if (hInstance&&dlgProc&&dlgid) l.Flags |= OFN_ENABLEHOOK|OFN_ENABLETEMPLATE|OFN_ENABLESIZING;
if (allowmul) l.Flags|=OFN_ALLOWMULTISELECT;
if (preservecwd) l.Flags|=OFN_NOCHANGEDIR;
if (initialfile) lstrcpyn_safe(temp,initialfile,temp_size);
WDL_fixfnforopenfn(temp);
if (!l.lpstrInitialDir||!l.lpstrInitialDir[0]) l.lpstrInitialDir=olddir;
int r = GetOpenFileName(&l);
if (preservecwd) SetCurrentDirectory(olddir);
if (!r) free(temp);
return r?temp:NULL;
#else
char if_temp[4096];
if (initialfile)
{
lstrcpyn_safe(if_temp,initialfile,sizeof(if_temp));
WDL_fixfnforopenfn(if_temp);
initialfile = if_temp;
}
// defext support?
BrowseFile_SetTemplate(dlgid,(DLGPROC)dlgProc,reshead);
char *ret = BrowseForFiles(text,initialdir,initialfile,allowmul,extlist);
if (preservecwd) SetCurrentDirectory(olddir);
return ret;
#endif
}
char *WDL_ChooseFileForOpen(HWND parent,
const char *text,
const char *initialdir,
const char *initialfile,
const char *extlist,
const char *defext,
bool preservecwd,
bool allowmul,
const char *dlgid,
void *dlgProc,
#ifdef _WIN32
HINSTANCE hInstance
#else
struct SWELL_DialogResourceIndex *reshead
#endif
)
{
return WDL_ChooseFileForOpen2(parent,text, initialdir,initialfile,extlist,defext,preservecwd,allowmul?1:0,dlgid,dlgProc,
#ifdef _WIN32
hInstance
#else
reshead
#endif
);
}