--- hatari/src/gui-sdl/dlgFileSelect.c 2019/04/09 08:49:43 1.1.1.9 +++ hatari/src/gui-sdl/dlgFileSelect.c 2019/04/09 08:54:40 1.1.1.12 @@ -1,8 +1,8 @@ /* Hatari - dlgFileSelect.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. + This file is distributed under the GNU General 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. */ @@ -23,18 +23,19 @@ const char DlgFileSelect_fileid[] = "Hat #define SGFS_NUMENTRIES 16 /* How many entries are displayed at once */ -#define SGFSDLG_FILENAME 5 -#define SGFSDLG_UPDIR 6 -#define SGFSDLG_HOMEDIR 7 -#define SGFSDLG_ROOTDIR 8 -#define SGFSDLG_ENTRYFIRST 11 -#define SGFSDLG_ENTRYLAST 26 -#define SGFSDLG_SCROLLBAR 27 -#define SGFSDLG_UP 28 -#define SGFSDLG_DOWN 29 -#define SGFSDLG_SHOWHIDDEN 30 -#define SGFSDLG_OKAY 31 -#define SGFSDLG_CANCEL 32 +#define SGFSDLG_FILENAME 5 +#define SGFSDLG_UPDIR 6 +#define SGFSDLG_CWD 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 @@ -48,6 +49,8 @@ static char dlgfname[DLGFNAME_SIZE+1]; #define DLGFILENAMES_SIZE 59 static char dlgfilenames[SGFS_NUMENTRIES][DLGFILENAMES_SIZE+1]; /* Visible file names in the dialog */ +#define SCROLLBAR_MIN_HEIGHT 4 /* Min value for yScrollbar_size */ + /* The dialog data: */ static SGOBJ fsdlg[] = { @@ -57,7 +60,8 @@ static SGOBJ fsdlg[] = { SGTEXT, 0, 0, 1,3, DLGPATH_SIZE,1, dlgpath }, { SGTEXT, 0, 0, 1,4, 6,1, "File:" }, { SGTEXT, 0, 0, 7,4, DLGFNAME_SIZE,1, dlgfname }, - { SGBUTTON, 0, 0, 51,1, 4,1, ".." }, + { SGBUTTON, 0, 0, 45,1, 4,1, ".." }, + { SGBUTTON, 0, 0, 50,1, 5,1, "CWD" }, { SGBUTTON, 0, 0, 56,1, 3,1, "~" }, { SGBUTTON, 0, 0, 60,1, 3,1, "/" }, { SGBOX, 0, 0, 1,6, 62,16, NULL }, @@ -88,13 +92,14 @@ static SGOBJ fsdlg[] = }; -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 ypos = -1; /* First entry number to be displayed. If -1, file selector start on the 1st file */ + /* else we continue from the previous position when SDLGui_FileSelect is called again */ +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 */ +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); @@ -236,8 +241,8 @@ static void DlgFileSelect_ManageScrollba int b, x, y; int scrollY, scrollYmin, scrollYmax, scrollH_half; float scrollMove; - - b = SDL_GetMouseState(&x, &y); + + SDL_GetMouseState(&x, &y); /* If mouse is down on the scrollbar for the first time */ if (fsdlg[SGFSDLG_SCROLLBAR].state & SG_MOUSEDOWN) { @@ -458,22 +463,29 @@ char* SDLGui_FileSelect(const char *path { struct dirent **files = NULL; char *pStringMem; - char *retpath; + char *retpath = NULL; 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; + bool bOldMouseVisibility; 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 */ + int yScrollbar_size; /* Size of the vertical scrollbar */ + + /* If this is the first call to SDLGui_FileSelect, we reset scrollbar_Ypos and ypos */ + /* Else, we keep the previous value of scrollbar_Ypos and update ypos below, to open */ + /* the fileselector at the same position it was used */ + if ( ypos < 0 ) + { + scrollbar_Ypos = 0.0; + ypos = 0; + } - ypos = 0; - scrollbar_Ypos = 0.0; refreshentries = true; entries = 0; @@ -487,6 +499,10 @@ char* SDLGui_FileSelect(const char *path fname[0] = 0; path[0] = 0; + /* Save mouse state and enable cursor */ + bOldMouseVisibility = SDL_ShowCursor(SDL_QUERY); + SDL_ShowCursor(SDL_ENABLE); + SDLGui_CenterDlg(fsdlg); if (bAllowNew) { @@ -511,8 +527,7 @@ char* SDLGui_FileSelect(const char *path if (!(File_DirExists(path) || getcwd(path, FILENAME_MAX))) { perror("SDLGui_FileSelect: non-existing path and CWD failed"); - free(pStringMem); - return NULL; + goto clean_exit; } } @@ -521,11 +536,6 @@ char* SDLGui_FileSelect(const char *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) @@ -538,8 +548,7 @@ char* SDLGui_FileSelect(const char *path if(!files) { fprintf(stderr, "SDLGui_FileSelect: ZIP_GetFilesDir error!\n"); - free(pStringMem); - return NULL; + goto clean_exit; } } else @@ -557,8 +566,7 @@ char* SDLGui_FileSelect(const char *path if (entries < 0) { fprintf(stderr, "SDLGui_FileSelect: Path not found.\n"); - free(pStringMem); - return NULL; + goto clean_exit; } /* reload always implies refresh */ @@ -568,22 +576,32 @@ char* SDLGui_FileSelect(const char *path /* Refresh scrollbar size */ if (entries <= SGFS_NUMENTRIES) - yScrolbar_size = (SGFS_NUMENTRIES-2) * sdlgui_fontheight; + yScrollbar_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; - + { + yScrollbar_size = (int)((SGFS_NUMENTRIES-2) / ((float)entries/(float)SGFS_NUMENTRIES) * sdlgui_fontheight); + if ( yScrollbar_size < SCROLLBAR_MIN_HEIGHT ) /* Value could be 0 for very large directory */ + yScrollbar_size = SCROLLBAR_MIN_HEIGHT; + } + fsdlg[SGFSDLG_SCROLLBAR].w = yScrollbar_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); - + + if (ypos+SGFS_NUMENTRIES >= entries) { /* Ensure Y pos is in the correct boundaries */ + ypos = entries - SGFS_NUMENTRIES; + if ( ypos < 0 ) + ypos = 0; + DlgFileSelect_Convert_ypos_to_scrollbar_Ypos(); + } + fsdlg[SGFSDLG_SCROLLBAR].h = (int) (scrollbar_Ypos * sdlgui_fontheight); + /* Update the file name strings in the dialog? */ if (refreshentries) { if (!DlgFileSelect_RefreshEntries(files, path, browsingzip)) { - free(pStringMem); - return NULL; + goto clean_exit; } refreshentries = false; } @@ -600,8 +618,7 @@ char* SDLGui_FileSelect(const char *path if (!tempstr) { perror("Error while allocating temporary memory in SDLGui_FileSelect()"); - free(pStringMem); - return NULL; + goto clean_exit; } if (browsingzip == true) @@ -610,8 +627,8 @@ char* SDLGui_FileSelect(const char *path zipdir, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name)) { fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n"); - free(pStringMem); - return NULL; + free(tempstr); + goto clean_exit; } /* directory? */ if (File_DoesFileNameEndWithSlash(tempstr)) @@ -665,8 +682,8 @@ char* SDLGui_FileSelect(const char *path path, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name)) { fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n"); - free(pStringMem); - return NULL; + free(tempstr); + goto clean_exit; } if (File_DirExists(tempstr)) { @@ -744,7 +761,11 @@ char* SDLGui_FileSelect(const char *path break; case SGFSDLG_HOMEDIR: /* Change to home directory */ - home = Paths_GetUserHome(); + case SGFSDLG_CWD: /* Change to current work directory */ + if (retbut == SGFSDLG_CWD) + home = Paths_GetWorkingDir(); + else + home = Paths_GetUserHome(); if (home == NULL || !*home) break; if (browsingzip) @@ -812,9 +833,6 @@ char* SDLGui_FileSelect(const char *path 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) @@ -832,6 +850,8 @@ char* SDLGui_FileSelect(const char *path } else retpath = NULL; +clean_exit: + SDL_ShowCursor(bOldMouseVisibility); free(pStringMem); return retpath; } @@ -845,7 +865,7 @@ char* SDLGui_FileSelect(const char *path * 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 + * (dlgname is shrunken & limited to maxlen and confname is assumed * to have FILENAME_MAX amount of space). */ bool SDLGui_FileConfSelect(char *dlgname, char *confname, int maxlen, bool bAllowNew)