Source to src/gui-sdl/dlgDiskSelect.c
/*
Previous - dlgDiskSelect.c
This file is distributed under the GNU Public License, version 2 or at
your option any later version. Read the file gpl.txt for details.
A file selection dialog for the graphical user interface for Hatari.
*/
const char DlgDiskSelect_fileid[] = "Previous dlgDiskSelect.c : " __DATE__ " " __TIME__;
#include <SDL.h>
#include <sys/stat.h>
#include <unistd.h>
#include "main.h"
#include "scandir.h"
#include "sdlgui.h"
#include "file.h"
#include "paths.h"
#include "zip.h"
#define SGFS_NUMENTRIES 16 /* How many entries are displayed at once */
#define SGFSDLG_READONLY 3
#define SGFSDLG_FILENAME 4
#define SGFSDLG_UPDIR 7
#define SGFSDLG_HOMEDIR 8
#define SGFSDLG_ROOTDIR 9
#define SGFSDLG_ENTRYFIRST 12
#define SGFSDLG_ENTRYLAST 27
#define SGFSDLG_SCROLLBAR 28
#define SGFSDLG_UP 29
#define SGFSDLG_DOWN 30
#define SGFSDLG_SHOWHIDDEN 31
#define SGFSDLG_OKAY 32
#define SGFSDLG_CANCEL 33
#define SCROLLOUT_ABOVE 1
#define SCROLLOUT_UNDER 2
#define DLGPATH_SIZE 40
static char dlgpath[DLGPATH_SIZE+1]; /* Path name in the dialog */
#define DLGFNAME_SIZE 36
static char dlgfname[DLGFNAME_SIZE+1]; /* Name of the selected file in the dialog */
#define DLGFILENAMES_SIZE 59
static char dlgfilenames[SGFS_NUMENTRIES][DLGFILENAMES_SIZE+1]; /* Visible file names in the dialog */
/* The dialog data: */
static SGOBJ fsdlg[] =
{
{ SGBOX, 0, 0, 0,0, 64,26, NULL },
{ SGTEXT, 0, 0, 25,1, 13,1, "Choose a file" },
{ SGTEXT, 0, 0, 1,3, 6,1, "Disk:" },
{ SGCHECKBOX, 0, 0, 46,3, 17,1, "Write protected" },
{ SGTEXT, 0, 0, 7,3, DLGFNAME_SIZE,1, dlgfname },
{ SGTEXT, 0, 0, 1,5, 7,1, "Path:" },
{ SGTEXT, 0, 0, 7,5, DLGPATH_SIZE,1, dlgpath },
{ SGBUTTON, 0, 0, 51,5, 4,1, ".." },
{ SGBUTTON, 0, 0, 56,5, 3,1, "~" },
{ SGBUTTON, 0, 0, 60,5, 3,1, "/" },
{ SGBOX, 0, 0, 1,7, 62,16, NULL },
{ SGBOX, 0, 0, 62,8, 1,14, NULL },
{ SGTEXT, SG_EXIT, 0, 2,7, DLGFILENAMES_SIZE,1, dlgfilenames[0] },
{ SGTEXT, SG_EXIT, 0, 2,8, DLGFILENAMES_SIZE,1, dlgfilenames[1] },
{ SGTEXT, SG_EXIT, 0, 2,9, DLGFILENAMES_SIZE,1, dlgfilenames[2] },
{ SGTEXT, SG_EXIT, 0, 2,10, DLGFILENAMES_SIZE,1, dlgfilenames[3] },
{ SGTEXT, SG_EXIT, 0, 2,11, DLGFILENAMES_SIZE,1, dlgfilenames[4] },
{ SGTEXT, SG_EXIT, 0, 2,12, DLGFILENAMES_SIZE,1, dlgfilenames[5] },
{ SGTEXT, SG_EXIT, 0, 2,13, DLGFILENAMES_SIZE,1, dlgfilenames[6] },
{ SGTEXT, SG_EXIT, 0, 2,14, DLGFILENAMES_SIZE,1, dlgfilenames[7] },
{ SGTEXT, SG_EXIT, 0, 2,15, DLGFILENAMES_SIZE,1, dlgfilenames[8] },
{ SGTEXT, SG_EXIT, 0, 2,16, DLGFILENAMES_SIZE,1, dlgfilenames[9] },
{ SGTEXT, SG_EXIT, 0, 2,17, DLGFILENAMES_SIZE,1, dlgfilenames[10] },
{ SGTEXT, SG_EXIT, 0, 2,18, DLGFILENAMES_SIZE,1, dlgfilenames[11] },
{ SGTEXT, SG_EXIT, 0, 2,19, DLGFILENAMES_SIZE,1, dlgfilenames[12] },
{ SGTEXT, SG_EXIT, 0, 2,20, DLGFILENAMES_SIZE,1, dlgfilenames[13] },
{ SGTEXT, SG_EXIT, 0, 2,21, DLGFILENAMES_SIZE,1, dlgfilenames[14] },
{ SGTEXT, SG_EXIT, 0, 2,22, DLGFILENAMES_SIZE,1, dlgfilenames[15] },
{ SGSCROLLBAR, SG_TOUCHEXIT, 0, 62, 8, 0, 0, NULL }, /* Scrollbar */
{ SGBUTTON, SG_TOUCHEXIT, 0, 62, 7,1,1, "\x01" }, /* Arrow up */
{ SGBUTTON, SG_TOUCHEXIT, 0, 62,22,1,1, "\x02" }, /* Arrow down */
{ SGCHECKBOX, SG_EXIT, 0, 2,24, 18,1, "Show hidden files" },
{ SGBUTTON, SG_DEFAULT, 0, 32,24, 8,1, "Okay" },
{ SGBUTTON, SG_CANCEL, 0, 50,24, 8,1, "Cancel" },
{ -1, 0, 0, 0,0, 0,0, NULL }
};
static int ypos; /* First entry number to be displayed */
static bool refreshentries; /* Do we have to update the file names in the dialog? */
static int entries; /* How many files are in the actual directory? */
static int oldMouseY = 0; /* Keep the latest Y mouse position for scrollbar move computing */
static int mouseClicked = 0; /* used to know if mouse if down for the first time or not */
static int mouseIsOut = 0; /* used to keep info that mouse if above or under the scrollbar when mousebutton is down */
static float scrollbar_Ypos = 0.0; /* scrollbar heigth */
/* Convert file position (in file list) to scrollbar y position */
static void DlgFileSelect_Convert_ypos_to_scrollbar_Ypos(void);
/*-----------------------------------------------------------------------*/
/**
* Update the file name strings in the dialog.
* Returns false if it failed, true on success.
*/
static int DlgFileSelect_RefreshEntries(struct dirent **files, char *path, bool browsingzip)
{
int i;
char *tempstr = malloc(FILENAME_MAX);
if (!tempstr)
{
perror("DlgFileSelect_RefreshEntries");
return false;
}
/* Copy entries to dialog: */
for (i=0; i<SGFS_NUMENTRIES; i++)
{
if (i+ypos < entries)
{
struct stat filestat;
/* Prepare entries: */
strcpy(tempstr, " ");
strcat(tempstr, files[i+ypos]->d_name);
File_ShrinkName(dlgfilenames[i], tempstr, DLGFILENAMES_SIZE);
/* Mark folders: */
strcpy(tempstr, path);
strcat(tempstr, files[i+ypos]->d_name);
if (browsingzip)
{
if (File_DoesFileNameEndWithSlash(tempstr))
dlgfilenames[i][0] = SGFOLDER; /* Mark folders */
}
else
{
if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
dlgfilenames[i][0] = SGFOLDER; /* Mark folders */
if (ZIP_FileNameIsZIP(tempstr) && browsingzip == false)
dlgfilenames[i][0] = SGFOLDER; /* Mark .ZIP archives as folders */
}
}
else
dlgfilenames[i][0] = 0; /* Clear entry */
}
free(tempstr);
return true;
}
/*-----------------------------------------------------------------------*/
/**
* Remove all hidden files (files with file names that begin with a dot) from
* the list.
*/
static void DlgFileSelect_RemoveHiddenFiles(struct dirent **files)
{
int i;
int nActPos = -1;
int nOldEntries;
nOldEntries = entries;
/* Scan list for hidden files and remove them. */
for (i = 0; i < nOldEntries; i++)
{
/* Does file name start with a dot? -> hidden file! */
if (files[i]->d_name[0] == '.')
{
if (nActPos == -1)
nActPos = i;
/* Remove file from list: */
free(files[i]);
files[i] = NULL;
entries -= 1;
}
}
/* Now close the gaps in the list: */
if (nActPos != -1)
{
for (i = nActPos; i < nOldEntries; i++)
{
if (files[i] != NULL)
{
/* Move entry to earlier position: */
files[nActPos] = files[i];
files[i] = NULL;
nActPos += 1;
}
}
}
}
/*-----------------------------------------------------------------------*/
/**
* Prepare to scroll up one entry.
*/
static void DlgFileSelect_ScrollUp(void)
{
if (ypos > 0)
{
--ypos;
DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
refreshentries = true;
}
}
/*-----------------------------------------------------------------------*/
/**
* Prepare to scroll down one entry.
*/
static void DlgFileSelect_ScrollDown(void)
{
if (ypos+SGFS_NUMENTRIES < entries)
{
++ypos;
DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
refreshentries = true;
}
}
/*-----------------------------------------------------------------------*/
/**
* Manage the scrollbar up or down.
*/
static void DlgFileSelect_ManageScrollbar(void)
{
int b, x, y;
int scrollY, scrollYmin, scrollYmax, scrollH_half;
float scrollMove;
b = SDL_GetMouseState(&x, &y);
/* If mouse is down on the scrollbar for the first time */
if (fsdlg[SGFSDLG_SCROLLBAR].state & SG_MOUSEDOWN) {
if (mouseClicked == 0) {
mouseClicked = 1;
mouseIsOut = 0;
oldMouseY = y;
}
}
/* Mouse button is up on the scrollbar */
else {
mouseClicked = 0;
oldMouseY = y;
mouseIsOut = 0;
}
/* If mouse Y position didn't change */
if (oldMouseY == y)
return;
/* Compute scrollbar ymin and ymax values */
scrollYmin = (fsdlg[SGFSDLG_SCROLLBAR].y + fsdlg[0].y) * sdlgui_fontheight;
scrollYmax = (fsdlg[SGFSDLG_DOWN].y + fsdlg[0].y) * sdlgui_fontheight;
scrollY = fsdlg[SGFSDLG_SCROLLBAR].y * sdlgui_fontheight + fsdlg[SGFSDLG_SCROLLBAR].h + fsdlg[0].y * sdlgui_fontheight;
scrollH_half = scrollY + fsdlg[SGFSDLG_SCROLLBAR].w / 2;
scrollMove = (float)(y-oldMouseY)/sdlgui_fontheight;
/* Verify if mouse is not above the scrollbar area */
if (y < scrollYmin) {
mouseIsOut = SCROLLOUT_ABOVE;
oldMouseY = y;
return;
}
if (mouseIsOut == SCROLLOUT_ABOVE && y < scrollH_half) {
oldMouseY = y;
return;
}
/* Verify if mouse is not under the scrollbar area */
if (y > scrollYmax) {
mouseIsOut = SCROLLOUT_UNDER;
oldMouseY = y;
return;
}
if (mouseIsOut == SCROLLOUT_UNDER && y > scrollH_half) {
oldMouseY = y;
return;
}
mouseIsOut = 0;
scrollbar_Ypos += scrollMove;
oldMouseY = y;
/* Verifiy if scrollbar is in correct inferior boundary */
if (scrollbar_Ypos < 0)
scrollbar_Ypos = 0.0;
/* Verifiy if scrollbar is in correct superior boundary */
b = (int) (scrollbar_Ypos * ((float)entries/(float)(SGFS_NUMENTRIES-2)) + 0.5);
if (b+SGFS_NUMENTRIES >= entries) {
ypos = entries - SGFS_NUMENTRIES;
DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
}
refreshentries = true;
}
/*-----------------------------------------------------------------------*/
/**
* Handle SDL events.
*/
static void DlgFileSelect_HandleSdlEvents(SDL_Event *pEvent)
{
int oldypos = ypos;
switch (pEvent->type)
{
case SDL_MOUSEWHEEL:
if (pEvent->wheel.y>0)
DlgFileSelect_ScrollUp();
else if (pEvent->wheel.y<0)
DlgFileSelect_ScrollDown();
break;
case SDL_KEYDOWN:
switch (pEvent->key.keysym.sym)
{
case SDLK_UP:
DlgFileSelect_ScrollUp();
break;
case SDLK_DOWN:
DlgFileSelect_ScrollDown();
break;
case SDLK_HOME:
ypos = 0;
DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
break;
case SDLK_END:
ypos = entries-SGFS_NUMENTRIES;
DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
break;
case SDLK_PAGEUP:
ypos -= SGFS_NUMENTRIES;
DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
break;
case SDLK_PAGEDOWN:
if (ypos+2*SGFS_NUMENTRIES < entries)
ypos += SGFS_NUMENTRIES;
else
ypos = entries-SGFS_NUMENTRIES;
DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
break;
default:
break;
}
break;
default:
break;
}
if (ypos < 0) {
ypos = 0;
scrollbar_Ypos = 0.0;
}
if (ypos != oldypos)
refreshentries = true;
}
/*-----------------------------------------------------------------------*/
/**
* Free file entries
*/
static struct dirent **files_free(struct dirent **files)
{
int i;
if (files != NULL)
{
for(i=0; i<entries; i++)
{
free(files[i]);
}
free(files);
}
return NULL;
}
/*-----------------------------------------------------------------------*/
/**
* Copy to dst src+add if they are below maxlen and return true,
* otherwise return false
*/
static int strcat_maxlen(char *dst, int maxlen, const char *src, const char *add)
{
int slen, alen;
slen = strlen(src);
alen = strlen(add);
if (slen + alen < maxlen)
{
strcpy(dst, src);
strcpy(dst+slen, add);
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------*/
/**
* Create and return suitable path into zip file
*/
static char* zip_get_path(const char *zipdir, const char *zipfilename, int browsingzip)
{
if (browsingzip)
{
char *zippath;
zippath = malloc(strlen(zipdir) + strlen(zipfilename) + 1);
strcpy(zippath, zipdir);
strcat(zippath, zipfilename);
return zippath;
}
return strdup("");
}
/**
* string for zip root needs to be empty, check and correct if needed
*/
static void correct_zip_root(char *zippath)
{
if (zippath[0] == PATHSEP && !zippath[1])
{
zippath[0] = '\0';
}
}
/**
* Convert Ypos to Y scrollbar position
*/
static void DlgFileSelect_Convert_ypos_to_scrollbar_Ypos(void)
{
if (entries <= SGFS_NUMENTRIES)
scrollbar_Ypos = 0.0;
else
scrollbar_Ypos = (float)ypos / ((float)entries/(float)(SGFS_NUMENTRIES-2));
}
/*-----------------------------------------------------------------------*/
/**
* Show and process a file selection dialog.
* Returns path/name user selected or NULL if user canceled
* input: zip_path = pointer's pointer to buffer to contain file path
* within a selected zip file, or NULL if browsing zip files is disallowed.
* bAllowNew: true if the user is allowed to insert new file names.
*/
static char* SDLGui_DiskSelectDialog(const char *path_and_name, char **zip_path, bool *readonly)
{
struct dirent **files = NULL;
char *pStringMem;
char *retpath;
const char *home;
char *path, *fname; /* The actual file and path names */
bool reloaddir = true; /* Do we have to reload the directory file list? */
int retbut;
int oldcursorstate;
int selection; /* The selection index */
char *zipfilename; /* Filename in zip file */
char *zipdir;
bool browsingzip = false; /* Are we browsing an archive? */
zip_dir *zipfiles = NULL;
SDL_Event sdlEvent;
int yScrolbar_size; /* Size of the vertical scrollbar */
ypos = 0;
scrollbar_Ypos = 0.0;
refreshentries = true;
entries = 0;
/* Allocate memory for the file and path name strings: */
pStringMem = malloc(4 * FILENAME_MAX);
path = pStringMem;
fname = pStringMem + FILENAME_MAX;
zipdir = pStringMem + 2 * FILENAME_MAX;
zipfilename = pStringMem + 3 * FILENAME_MAX;
zipfilename[0] = 0;
fname[0] = 0;
path[0] = 0;
SDLGui_CenterDlg(fsdlg);
/* Prepare the path and filename variables */
if (path_and_name && path_and_name[0])
{
strncpy(path, path_and_name, FILENAME_MAX);
path[FILENAME_MAX-1] = '\0';
}
if (!File_DirExists(path))
{
File_SplitPath(path, path, fname, NULL);
if (!(File_DirExists(path) || getcwd(path, FILENAME_MAX)))
{
perror("SDLGui_FileSelect: non-existing path and CWD failed");
free(pStringMem);
return NULL;
}
}
File_MakeAbsoluteName(path);
File_MakeValidPathName(path);
File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
/* Save old mouse cursor state and enable cursor */
oldcursorstate = SDL_ShowCursor(SDL_QUERY);
if (oldcursorstate == SDL_DISABLE)
SDL_ShowCursor(SDL_ENABLE);
do
{
if (reloaddir)
{
files = files_free(files);
if (browsingzip)
{
files = ZIP_GetFilesDir(zipfiles, zipdir, &entries);
if(!files)
{
fprintf(stderr, "SDLGui_FileSelect: ZIP_GetFilesDir error!\n");
free(pStringMem);
return NULL;
}
}
else
{
/* Load directory entries: */
entries = scandir(path, &files, 0, alphasort);
}
/* Remove hidden files from the list if necessary: */
if (!(fsdlg[SGFSDLG_SHOWHIDDEN].state & SG_SELECTED))
{
DlgFileSelect_RemoveHiddenFiles(files);
}
if (entries < 0)
{
fprintf(stderr, "SDLGui_FileSelect: Path not found.\n");
free(pStringMem);
return NULL;
}
/* reload always implies refresh */
reloaddir = false;
refreshentries = true;
}/* reloaddir */
/* Refresh scrollbar size */
if (entries <= SGFS_NUMENTRIES)
yScrolbar_size = (SGFS_NUMENTRIES-2) * sdlgui_fontheight;
else
yScrolbar_size = (int)((SGFS_NUMENTRIES-2) / ((float)entries/(float)SGFS_NUMENTRIES) * sdlgui_fontheight);
fsdlg[SGFSDLG_SCROLLBAR].w = yScrolbar_size;
/* Refresh scrolbar pos */
fsdlg[SGFSDLG_SCROLLBAR].h = (int) (scrollbar_Ypos * sdlgui_fontheight);
ypos = (int) (scrollbar_Ypos * ((float)entries/(float)(SGFS_NUMENTRIES-2)) + 0.5);
/* Update the file name strings in the dialog? */
if (refreshentries)
{
if (!DlgFileSelect_RefreshEntries(files, path, browsingzip))
{
free(pStringMem);
return NULL;
}
refreshentries = false;
}
/* Show read-only status */
if (*readonly)
fsdlg[SGFSDLG_READONLY].state |= SG_SELECTED;
else
fsdlg[SGFSDLG_READONLY].state &= ~SG_SELECTED;
/* Show dialog: */
retbut = SDLGui_DoDialog(fsdlg, &sdlEvent);
/* Has the user clicked on a file or folder? */
if (retbut>=SGFSDLG_ENTRYFIRST && retbut<=SGFSDLG_ENTRYLAST && retbut-SGFSDLG_ENTRYFIRST+ypos<entries)
{
char *tempstr;
tempstr = malloc(FILENAME_MAX);
if (!tempstr)
{
perror("Error while allocating temporary memory in SDLGui_FileSelect()");
free(pStringMem);
return NULL;
}
if (browsingzip == true)
{
if (!strcat_maxlen(tempstr, FILENAME_MAX,
zipdir, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name))
{
fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
free(pStringMem);
return NULL;
}
/* directory? */
if (File_DoesFileNameEndWithSlash(tempstr))
{
/* handle the ../ directory */
if (strcmp(files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name, "../") == 0)
{
/* close the zip file */
if (strcmp(tempstr, "../") == 0)
{
/* free zip file entries */
ZIP_FreeZipDir(zipfiles);
zipfiles = NULL;
/* Copy the path name to the dialog */
File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
browsingzip = false;
}
else
{
/* remove "../" and previous dir from path */
File_PathShorten(tempstr, 2);
correct_zip_root(tempstr);
strcpy(zipdir, tempstr);
File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
}
}
else /* not the "../" directory */
{
strcpy(zipdir, tempstr);
File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
}
reloaddir = true;
/* Copy the path name to the dialog */
zipfilename[0] = '\0';
dlgfname[0] = 0;
ypos = 0;
scrollbar_Ypos = 0.0;
}
else
{
/* not dir, select a file in the zip */
selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
strcpy(zipfilename, files[selection]->d_name);
File_ShrinkName(dlgfname, zipfilename, DLGFNAME_SIZE);
}
}
else /* not browsingzip */
{
if (!strcat_maxlen(tempstr, FILENAME_MAX,
path, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name))
{
fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
free(pStringMem);
return NULL;
}
if (File_DirExists(tempstr))
{
File_HandleDotDirs(tempstr);
File_AddSlashToEndFileName(tempstr);
/* Copy the path name to the dialog */
File_ShrinkName(dlgpath, tempstr, DLGPATH_SIZE);
strcpy(path, tempstr);
reloaddir = true;
dlgfname[0] = 0;
ypos = 0;
scrollbar_Ypos = 0.0;
}
else if (ZIP_FileNameIsZIP(tempstr) && zip_path != NULL)
{
/* open a zip file */
zipfiles = ZIP_GetFiles(tempstr);
if (zipfiles != NULL && browsingzip == false)
{
selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
strcpy(fname, files[selection]->d_name);
File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
browsingzip = true;
zipdir[0] = '\0'; /* zip root */
File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
reloaddir = true;
ypos = 0;
scrollbar_Ypos = 0.0;
}
}
else
{
/* Select a file */
selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
strcpy(fname, files[selection]->d_name);
File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
}
} /* not browsingzip */
free(tempstr);
}
else /* Has the user clicked on another button? */
{
switch(retbut)
{
case SGFSDLG_READONLY: /* Change disk protection */
if (*readonly)
*readonly=false;
else
*readonly=true;
break;
case SGFSDLG_UPDIR: /* Change path to parent directory */
if (browsingzip)
{
/* close the zip file? */
if (!zipdir[0])
{
/* free zip file entries */
ZIP_FreeZipDir(zipfiles);
browsingzip = false;
zipfiles = NULL;
File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
}
else
{
/* remove last dir from zipdir path */
File_PathShorten(zipdir, 1);
correct_zip_root(zipdir);
File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
zipfilename[0] = '\0';
}
} /* not a zip file: */
else
{
File_PathShorten(path, 1);
File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
}
reloaddir = true;
break;
case SGFSDLG_HOMEDIR: /* Change to home directory */
home = Paths_GetUserHome();
if (home == NULL || !*home)
break;
if (browsingzip)
{
/* free zip file entries */
ZIP_FreeZipDir(zipfiles);
zipfiles = NULL;
browsingzip = false;
}
strcpy(path, home);
File_AddSlashToEndFileName(path);
File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
reloaddir = true;
break;
case SGFSDLG_ROOTDIR: /* Change to root directory */
if (browsingzip)
{
/* free zip file entries */
ZIP_FreeZipDir(zipfiles);
zipfiles = NULL;
browsingzip = false;
}
path[0] = PATHSEP; path[1] = '\0';
strcpy(dlgpath, path);
reloaddir = true;
break;
case SGFSDLG_UP: /* Scroll up */
DlgFileSelect_ScrollUp();
SDL_Delay(10);
break;
case SGFSDLG_DOWN: /* Scroll down */
DlgFileSelect_ScrollDown();
SDL_Delay(10);
break;
case SGFSDLG_SCROLLBAR: /* Scrollbar selected */
DlgFileSelect_ManageScrollbar();
SDL_Delay(10);
break;
case SGFSDLG_FILENAME: /* User entered new filename */
strcpy(fname, dlgfname);
break;
case SGFSDLG_SHOWHIDDEN: /* Show/hide hidden files */
reloaddir = true;
ypos = 0;
scrollbar_Ypos = 0.0;
break;
case SDLGUI_UNKNOWNEVENT:
DlgFileSelect_HandleSdlEvents(&sdlEvent);
break;
} /* switch */
if (reloaddir)
{
/* Remove old selection */
fname[0] = 0;
dlgfname[0] = 0;
ypos = 0;
scrollbar_Ypos = 0.0;
}
} /* other button code */
} /* do */
while (retbut!=SGFSDLG_OKAY && retbut!=SGFSDLG_CANCEL
&& retbut!=SDLGUI_QUIT && retbut != SDLGUI_ERROR && !bQuitProgram);
if (oldcursorstate == SDL_DISABLE)
SDL_ShowCursor(SDL_DISABLE);
files_free(files);
if (browsingzip)
{
/* free zip file entries */
ZIP_FreeZipDir(zipfiles);
zipfiles = NULL;
}
if (retbut == SGFSDLG_OKAY)
{
if (zip_path)
*zip_path = zip_get_path(zipdir, zipfilename, browsingzip);
retpath = File_MakePath(path, fname, NULL);
}
else
retpath = NULL;
free(pStringMem);
return retpath;
}
/*-----------------------------------------------------------------------*/
/**
* Let user browse for a file, confname is used as default.
* If bAllowNew is true, user can select new files also.
*
* If no file is selected, or there's some problem with the file,
* return false and clear dlgname & confname.
* Otherwise return true, set dlgname & confname to the new file name
* (dlgname is shrinked & limited to maxlen and confname is assumed
* to have FILENAME_MAX amount of space).
*/
bool SDLGui_DiskSelect(char *dlgname, char *confname, int maxlen, bool *readonly)
{
char *selname;
selname = SDLGui_DiskSelectDialog(confname, NULL, readonly);
if (selname)
{
if (!File_DoesFileNameEndWithSlash(selname) && File_Exists(selname))
{
strncpy(confname, selname, FILENAME_MAX);
confname[FILENAME_MAX-1] = '\0';
File_ShrinkName(dlgname, selname, maxlen);
}
else
{
dlgname[0] = confname[0] = 0;
free(selname);
return false;
}
free(selname);
return true;
}
return false;
}