Annotation of hatari/src/gui-sdl/dlgFileSelect.c, revision 1.1.1.9

1.1       root        1: /*
                      2:   Hatari - dlgFileSelect.c
                      3:  
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6:  
                      7:   A file selection dialog for the graphical user interface for Hatari.
                      8: */
1.1.1.7   root        9: const char DlgFileSelect_fileid[] = "Hatari dlgFileSelect.c : " __DATE__ " " __TIME__;
1.1       root       10: 
                     11: #include <SDL.h>
                     12: #include <sys/stat.h>
                     13: #include <unistd.h>
                     14: 
                     15: #include "main.h"
1.1.1.3   root       16: #include "scandir.h"
1.1       root       17: #include "sdlgui.h"
                     18: #include "file.h"
1.1.1.8   root       19: #include "paths.h"
1.1       root       20: #include "zip.h"
                     21: 
                     22: 
1.1.1.2   root       23: #define SGFS_NUMENTRIES   16            /* How many entries are displayed at once */
                     24: 
                     25: 
1.1.1.9 ! root       26: #define SGFSDLG_FILENAME   5
        !            27: #define SGFSDLG_UPDIR      6
        !            28: #define SGFSDLG_HOMEDIR    7
        !            29: #define SGFSDLG_ROOTDIR    8
        !            30: #define SGFSDLG_ENTRYFIRST 11
        !            31: #define SGFSDLG_ENTRYLAST 26
        !            32: #define SGFSDLG_SCROLLBAR 27
        !            33: #define SGFSDLG_UP        28
        !            34: #define SGFSDLG_DOWN      29
        !            35: #define SGFSDLG_SHOWHIDDEN 30
        !            36: #define SGFSDLG_OKAY      31
        !            37: #define SGFSDLG_CANCEL    32
1.1       root       38: 
1.1.1.9 ! root       39: #define SCROLLOUT_ABOVE  1
        !            40: #define SCROLLOUT_UNDER  2
1.1       root       41: 
                     42: #define DLGPATH_SIZE 62
                     43: static char dlgpath[DLGPATH_SIZE+1];    /* Path name in the dialog */
                     44: 
                     45: #define DLGFNAME_SIZE 56
                     46: static char dlgfname[DLGFNAME_SIZE+1];  /* Name of the selected file in the dialog */
                     47: 
                     48: #define DLGFILENAMES_SIZE 59
1.1.1.2   root       49: static char dlgfilenames[SGFS_NUMENTRIES][DLGFILENAMES_SIZE+1];  /* Visible file names in the dialog */
1.1       root       50: 
                     51: /* The dialog data: */
                     52: static SGOBJ fsdlg[] =
                     53: {
                     54:        { SGBOX, 0, 0, 0,0, 64,25, NULL },
                     55:        { SGTEXT, 0, 0, 25,1, 13,1, "Choose a file" },
                     56:        { SGTEXT, 0, 0, 1,2, 7,1, "Folder:" },
                     57:        { SGTEXT, 0, 0, 1,3, DLGPATH_SIZE,1, dlgpath },
                     58:        { SGTEXT, 0, 0, 1,4, 6,1, "File:" },
                     59:        { SGTEXT, 0, 0, 7,4, DLGFNAME_SIZE,1, dlgfname },
1.1.1.3   root       60:        { SGBUTTON, 0, 0, 51,1, 4,1, ".." },
                     61:        { SGBUTTON, 0, 0, 56,1, 3,1, "~" },
1.1       root       62:        { SGBUTTON, 0, 0, 60,1, 3,1, "/" },
                     63:        { SGBOX, 0, 0, 1,6, 62,16, NULL },
                     64:        { SGBOX, 0, 0, 62,7, 1,14, NULL },
                     65:        { SGTEXT, SG_EXIT, 0, 2,6, DLGFILENAMES_SIZE,1, dlgfilenames[0] },
                     66:        { SGTEXT, SG_EXIT, 0, 2,7, DLGFILENAMES_SIZE,1, dlgfilenames[1] },
                     67:        { SGTEXT, SG_EXIT, 0, 2,8, DLGFILENAMES_SIZE,1, dlgfilenames[2] },
                     68:        { SGTEXT, SG_EXIT, 0, 2,9, DLGFILENAMES_SIZE,1, dlgfilenames[3] },
                     69:        { SGTEXT, SG_EXIT, 0, 2,10, DLGFILENAMES_SIZE,1, dlgfilenames[4] },
                     70:        { SGTEXT, SG_EXIT, 0, 2,11, DLGFILENAMES_SIZE,1, dlgfilenames[5] },
                     71:        { SGTEXT, SG_EXIT, 0, 2,12, DLGFILENAMES_SIZE,1, dlgfilenames[6] },
                     72:        { SGTEXT, SG_EXIT, 0, 2,13, DLGFILENAMES_SIZE,1, dlgfilenames[7] },
                     73:        { SGTEXT, SG_EXIT, 0, 2,14, DLGFILENAMES_SIZE,1, dlgfilenames[8] },
                     74:        { SGTEXT, SG_EXIT, 0, 2,15, DLGFILENAMES_SIZE,1, dlgfilenames[9] },
                     75:        { SGTEXT, SG_EXIT, 0, 2,16, DLGFILENAMES_SIZE,1, dlgfilenames[10] },
                     76:        { SGTEXT, SG_EXIT, 0, 2,17, DLGFILENAMES_SIZE,1, dlgfilenames[11] },
                     77:        { SGTEXT, SG_EXIT, 0, 2,18, DLGFILENAMES_SIZE,1, dlgfilenames[12] },
                     78:        { SGTEXT, SG_EXIT, 0, 2,19, DLGFILENAMES_SIZE,1, dlgfilenames[13] },
                     79:        { SGTEXT, SG_EXIT, 0, 2,20, DLGFILENAMES_SIZE,1, dlgfilenames[14] },
                     80:        { SGTEXT, SG_EXIT, 0, 2,21, DLGFILENAMES_SIZE,1, dlgfilenames[15] },
1.1.1.9 ! root       81:        { SGSCROLLBAR, SG_TOUCHEXIT, 0, 62, 7, 0, 0, NULL },       /* Scrollbar */
        !            82:        { SGBUTTON, SG_TOUCHEXIT, 0, 62, 6,1,1, "\x01" },          /* Arrow up */
        !            83:        { SGBUTTON, SG_TOUCHEXIT, 0, 62,21,1,1, "\x02" },          /* Arrow down */
1.1.1.5   root       84:        { SGCHECKBOX, SG_EXIT, 0, 2,23, 18,1, "Show hidden files" },
1.1.1.4   root       85:        { SGBUTTON, SG_DEFAULT, 0, 32,23, 8,1, "Okay" },
                     86:        { SGBUTTON, SG_CANCEL, 0, 50,23, 8,1, "Cancel" },
1.1       root       87:        { -1, 0, 0, 0,0, 0,0, NULL }
                     88: };
                     89: 
                     90: 
1.1.1.2   root       91: static int ypos;                        /* First entry number to be displayed */
1.1.1.5   root       92: static bool refreshentries;             /* Do we have to update the file names in the dialog? */
1.1.1.2   root       93: static int entries;                     /* How many files are in the actual directory? */
1.1.1.9 ! root       94: static int oldMouseY = 0;                              /* Keep the latest Y mouse position for scrollbar move computing */
        !            95: static int mouseClicked = 0;                   /* used to know if mouse if down for the first time or not */
        !            96: static int mouseIsOut = 0;                             /* used to keep info that mouse if above or under the scrollbar when mousebutton is down */
        !            97: static float scrollbar_Ypos = 0.0;         /* scrollbar heigth */
        !            98: 
        !            99: /* Convert file position (in file list) to scrollbar y position */
        !           100: static void DlgFileSelect_Convert_ypos_to_scrollbar_Ypos(void);
        !           101: 
1.1.1.2   root      102: 
1.1       root      103: 
                    104: /*-----------------------------------------------------------------------*/
1.1.1.8   root      105: /**
                    106:  * Update the file name strings in the dialog.
                    107:  * Returns false if it failed, true on success.
                    108:  */
1.1.1.5   root      109: static int DlgFileSelect_RefreshEntries(struct dirent **files, char *path, bool browsingzip)
1.1       root      110: {
                    111:        int i;
                    112:        char *tempstr = malloc(FILENAME_MAX);
                    113: 
                    114:        if (!tempstr)
                    115:        {
                    116:                perror("DlgFileSelect_RefreshEntries");
1.1.1.7   root      117:                return false;
1.1       root      118:        }
                    119: 
                    120:        /* Copy entries to dialog: */
1.1.1.4   root      121:        for (i=0; i<SGFS_NUMENTRIES; i++)
1.1       root      122:        {
1.1.1.4   root      123:                if (i+ypos < entries)
1.1       root      124:                {
                    125:                        struct stat filestat;
                    126:                        /* Prepare entries: */
                    127:                        strcpy(tempstr, "  ");
                    128:                        strcat(tempstr, files[i+ypos]->d_name);
                    129:                        File_ShrinkName(dlgfilenames[i], tempstr, DLGFILENAMES_SIZE);
                    130:                        /* Mark folders: */
                    131:                        strcpy(tempstr, path);
                    132:                        strcat(tempstr, files[i+ypos]->d_name);
                    133: 
1.1.1.4   root      134:                        if (browsingzip)
1.1       root      135:                        {
1.1.1.3   root      136:                                if (File_DoesFileNameEndWithSlash(tempstr))
1.1       root      137:                                        dlgfilenames[i][0] = SGFOLDER;    /* Mark folders */
                    138:                        }
                    139:                        else
                    140:                        {
                    141:                                if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
                    142:                                        dlgfilenames[i][0] = SGFOLDER;    /* Mark folders */
1.1.1.7   root      143:                                if (ZIP_FileNameIsZIP(tempstr) && browsingzip == false)
1.1       root      144:                                        dlgfilenames[i][0] = SGFOLDER;    /* Mark .ZIP archives as folders */
                    145:                        }
                    146:                }
                    147:                else
                    148:                        dlgfilenames[i][0] = 0;  /* Clear entry */
                    149:        }
                    150: 
                    151:        free(tempstr);
1.1.1.7   root      152:        return true;
1.1       root      153: }
                    154: 
                    155: 
                    156: /*-----------------------------------------------------------------------*/
1.1.1.8   root      157: /**
                    158:  * Remove all hidden files (files with file names that begin with a dot) from
                    159:  * the list.
                    160:  */
1.1.1.3   root      161: static void DlgFileSelect_RemoveHiddenFiles(struct dirent **files)
                    162: {
                    163:        int i;
                    164:        int nActPos = -1;
                    165:        int nOldEntries;
                    166: 
                    167:        nOldEntries = entries;
                    168: 
                    169:        /* Scan list for hidden files and remove them. */
                    170:        for (i = 0; i < nOldEntries; i++)
                    171:        {
                    172:                /* Does file name start with a dot? -> hidden file! */
                    173:                if (files[i]->d_name[0] == '.')
                    174:                {
                    175:                        if (nActPos == -1)
                    176:                                nActPos = i;
                    177:                        /* Remove file from list: */
                    178:                        free(files[i]);
                    179:                        files[i] = NULL;
                    180:                        entries -= 1;
                    181:                }
                    182:        }
                    183: 
                    184:        /* Now close the gaps in the list: */
                    185:        if (nActPos != -1)
                    186:        {
                    187:                for (i = nActPos; i < nOldEntries; i++)
                    188:                {
                    189:                        if (files[i] != NULL)
                    190:                        {
                    191:                                /* Move entry to earlier position: */
                    192:                                files[nActPos] = files[i];
                    193:                                files[i] = NULL;
                    194:                                nActPos += 1;
                    195:                        }
                    196:                }
                    197:        }
                    198: }
                    199: 
                    200: 
                    201: /*-----------------------------------------------------------------------*/
1.1.1.8   root      202: /**
                    203:  * Prepare to scroll up one entry.
                    204:  */
1.1.1.2   root      205: static void DlgFileSelect_ScrollUp(void)
                    206: {
                    207:        if (ypos > 0)
                    208:        {
                    209:                --ypos;
1.1.1.9 ! root      210:                DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
1.1.1.7   root      211:                refreshentries = true;
1.1.1.2   root      212:        }
                    213: }
                    214: 
                    215: 
                    216: /*-----------------------------------------------------------------------*/
1.1.1.8   root      217: /**
                    218:  * Prepare to scroll down one entry.
                    219:  */
1.1.1.2   root      220: static void DlgFileSelect_ScrollDown(void)
                    221: {
                    222:        if (ypos+SGFS_NUMENTRIES < entries)
                    223:        {
                    224:                ++ypos;
1.1.1.9 ! root      225:                DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
1.1.1.7   root      226:                refreshentries = true;
1.1.1.2   root      227:        }
                    228: }
                    229: 
1.1.1.9 ! root      230: /*-----------------------------------------------------------------------*/
        !           231: /**
        !           232:  * Manage the scrollbar up or down.
        !           233:  */
        !           234: static void DlgFileSelect_ManageScrollbar(void)
        !           235: {
        !           236:        int b, x, y;
        !           237:        int scrollY, scrollYmin, scrollYmax, scrollH_half;
        !           238:        float scrollMove;
        !           239:        
        !           240:        b = SDL_GetMouseState(&x, &y);
        !           241: 
        !           242:        /* If mouse is down on the scrollbar for the first time */
        !           243:        if (fsdlg[SGFSDLG_SCROLLBAR].state & SG_MOUSEDOWN) {
        !           244:                if (mouseClicked == 0) {
        !           245:                        mouseClicked = 1;
        !           246:                        mouseIsOut = 0;
        !           247:                        oldMouseY = y;
        !           248:                }
        !           249:        }
        !           250:        /* Mouse button is up on the scrollbar */
        !           251:        else {
        !           252:                mouseClicked = 0;
        !           253:                oldMouseY = y;
        !           254:                mouseIsOut = 0;
        !           255:        }
        !           256:        
        !           257:        /* If mouse Y position didn't change */ 
        !           258:        if (oldMouseY == y)
        !           259:                return;
        !           260: 
        !           261:        /* Compute scrollbar ymin and ymax values */ 
        !           262: 
        !           263:        scrollYmin = (fsdlg[SGFSDLG_SCROLLBAR].y + fsdlg[0].y) * sdlgui_fontheight;
        !           264:        scrollYmax = (fsdlg[SGFSDLG_DOWN].y + fsdlg[0].y) * sdlgui_fontheight;
        !           265:        
        !           266:        scrollY = fsdlg[SGFSDLG_SCROLLBAR].y * sdlgui_fontheight + fsdlg[SGFSDLG_SCROLLBAR].h + fsdlg[0].y * sdlgui_fontheight;
        !           267:        scrollH_half = scrollY + fsdlg[SGFSDLG_SCROLLBAR].w / 2;
        !           268:        scrollMove = (float)(y-oldMouseY)/sdlgui_fontheight;
        !           269:        
        !           270:        /* Verify if mouse is not above the scrollbar area */
        !           271:        if (y < scrollYmin) {
        !           272:                mouseIsOut = SCROLLOUT_ABOVE;
        !           273:                oldMouseY = y;
        !           274:                return;
        !           275:        }
        !           276:        if (mouseIsOut == SCROLLOUT_ABOVE && y < scrollH_half) {
        !           277:                oldMouseY = y;
        !           278:                return;
        !           279:        }
        !           280: 
        !           281:        /* Verify if mouse is not under the scrollbar area */
        !           282:        if (y > scrollYmax) {
        !           283:                mouseIsOut = SCROLLOUT_UNDER;
        !           284:                oldMouseY = y;
        !           285:                return;
        !           286:        }
        !           287:        if (mouseIsOut == SCROLLOUT_UNDER && y > scrollH_half) {
        !           288:                oldMouseY = y;
        !           289:                return;
        !           290:        }
        !           291: 
        !           292:        mouseIsOut = 0;
        !           293: 
        !           294:        scrollbar_Ypos += scrollMove;
        !           295:        oldMouseY = y;
        !           296: 
        !           297:        /* Verifiy if scrollbar is in correct inferior boundary */
        !           298:        if (scrollbar_Ypos < 0)
        !           299:                scrollbar_Ypos = 0.0;
        !           300: 
        !           301:        /* Verifiy if scrollbar is in correct superior boundary */
        !           302:        b = (int) (scrollbar_Ypos * ((float)entries/(float)(SGFS_NUMENTRIES-2)) + 0.5);
        !           303:        if (b+SGFS_NUMENTRIES >= entries) {
        !           304:                ypos = entries - SGFS_NUMENTRIES;
        !           305:                DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
        !           306:        }
        !           307: 
        !           308:        refreshentries = true;                  
        !           309: }
1.1.1.2   root      310: 
                    311: /*-----------------------------------------------------------------------*/
1.1.1.8   root      312: /**
                    313:  * Handle SDL events.
                    314:  */
1.1.1.2   root      315: static void DlgFileSelect_HandleSdlEvents(SDL_Event *pEvent)
                    316: {
1.1.1.4   root      317:        int oldypos = ypos;
1.1.1.2   root      318:        switch (pEvent->type)
                    319:        {
                    320:         case SDL_MOUSEBUTTONDOWN:
                    321:                if (pEvent->button.button == SDL_BUTTON_WHEELUP)
                    322:                        DlgFileSelect_ScrollUp();
                    323:                else if (pEvent->button.button == SDL_BUTTON_WHEELDOWN)
                    324:                        DlgFileSelect_ScrollDown();
                    325:                break;
1.1.1.9 ! root      326:         case SDL_KEYDOWN:              
1.1.1.2   root      327:                switch (pEvent->key.keysym.sym)
                    328:                {
1.1.1.9 ! root      329:                 case SDLK_UP:
        !           330:                        DlgFileSelect_ScrollUp();
        !           331:                        break;
        !           332:                 case SDLK_DOWN:
        !           333:                        DlgFileSelect_ScrollDown();
        !           334:                        break;
        !           335:                 case SDLK_HOME:
        !           336:                        ypos = 0; 
        !           337:                        DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
        !           338:                        break;
        !           339:                 case SDLK_END:
        !           340:                    ypos = entries-SGFS_NUMENTRIES; 
        !           341:                        DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
        !           342:                    break;
        !           343:                 case SDLK_PAGEUP:
        !           344:                    ypos -= SGFS_NUMENTRIES;
        !           345:                        DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
        !           346:                    break;
1.1.1.2   root      347:                 case SDLK_PAGEDOWN:
                    348:                        if (ypos+2*SGFS_NUMENTRIES < entries)
                    349:                                ypos += SGFS_NUMENTRIES;
                    350:                        else
                    351:                                ypos = entries-SGFS_NUMENTRIES;
1.1.1.9 ! root      352:                        DlgFileSelect_Convert_ypos_to_scrollbar_Ypos();
1.1.1.2   root      353:                        break;
1.1.1.4   root      354:                 default:
                    355:                        break;
1.1.1.2   root      356:                }
                    357:                break;
1.1.1.4   root      358:        default:
                    359:                break;
                    360:        }
1.1.1.9 ! root      361:        
        !           362:        if (ypos < 0) {
1.1.1.4   root      363:                ypos = 0;
1.1.1.9 ! root      364:                scrollbar_Ypos = 0.0;
        !           365:        }
        !           366:        
1.1.1.4   root      367:        if (ypos != oldypos)
1.1.1.7   root      368:                refreshentries = true;
1.1.1.4   root      369: }
                    370: 
                    371: 
                    372: /*-----------------------------------------------------------------------*/
1.1.1.8   root      373: /**
                    374:  * Free file entries
                    375:  */
1.1.1.4   root      376: static struct dirent **files_free(struct dirent **files)
                    377: {
                    378:        int i;
                    379:        if (files != NULL)
                    380:        {
                    381:                for(i=0; i<entries; i++)
                    382:                {
                    383:                        free(files[i]);
                    384:                }
                    385:                free(files);
                    386:        }
                    387:        return NULL;
                    388: }
                    389: 
                    390: 
                    391: /*-----------------------------------------------------------------------*/
1.1.1.8   root      392: /**
                    393:  * Copy to dst src+add if they are below maxlen and return true,
                    394:  * otherwise return false
                    395:  */
1.1.1.4   root      396: static int strcat_maxlen(char *dst, int maxlen, const char *src, const char *add)
                    397: {
                    398:        int slen, alen;
                    399:        slen = strlen(src);
                    400:        alen = strlen(add);
                    401:        if (slen + alen < maxlen)
                    402:        {
                    403:                strcpy(dst, src);
                    404:                strcpy(dst+slen, add);
                    405:                return 1;
                    406:        }
                    407:        return 0;
                    408: }
                    409: 
                    410: /*-----------------------------------------------------------------------*/
1.1.1.8   root      411: /**
                    412:  * Create and return suitable path into zip file
                    413:  */
1.1.1.4   root      414: static char* zip_get_path(const char *zipdir, const char *zipfilename, int browsingzip)
                    415: {
                    416:        if (browsingzip)
                    417:        {
                    418:                char *zippath;
                    419:                zippath = malloc(strlen(zipdir) + strlen(zipfilename) + 1);
                    420:                strcpy(zippath, zipdir);
                    421:                strcat(zippath, zipfilename);
                    422:                return zippath;
1.1.1.2   root      423:        }
1.1.1.4   root      424:        return strdup("");
1.1.1.2   root      425: }
                    426: 
1.1.1.8   root      427: /**
                    428:  * string for zip root needs to be empty, check and correct if needed
                    429:  */
1.1.1.4   root      430: static void correct_zip_root(char *zippath)
                    431: {
                    432:        if (zippath[0] == PATHSEP && !zippath[1])
                    433:        {
                    434:                zippath[0] = '\0';
                    435:        }
                    436: }
1.1.1.2   root      437: 
1.1.1.9 ! root      438: /**
        !           439:  * Convert Ypos to Y scrollbar position
        !           440:  */
        !           441: static void DlgFileSelect_Convert_ypos_to_scrollbar_Ypos(void)
        !           442: {
        !           443:        if (entries <= SGFS_NUMENTRIES)
        !           444:                scrollbar_Ypos = 0.0;
        !           445:        else
        !           446:                scrollbar_Ypos = (float)ypos / ((float)entries/(float)(SGFS_NUMENTRIES-2));
        !           447: }
        !           448: 
1.1.1.2   root      449: /*-----------------------------------------------------------------------*/
1.1.1.8   root      450: /**
                    451:  * Show and process a file selection dialog.
                    452:  * Returns path/name user selected or NULL if user canceled
                    453:  * input: zip_path = pointer's pointer to buffer to contain file path
                    454:  * within a selected zip file, or NULL if browsing zip files is disallowed.
                    455:  * bAllowNew: true if the user is allowed to insert new file names.
                    456:  */
1.1.1.5   root      457: char* SDLGui_FileSelect(const char *path_and_name, char **zip_path, bool bAllowNew)
1.1       root      458: {
                    459:        struct dirent **files = NULL;
                    460:        char *pStringMem;
1.1.1.4   root      461:        char *retpath;
1.1.1.8   root      462:        const char *home;
                    463:        char *path, *fname;                 /* The actual file and path names */
1.1.1.7   root      464:        bool reloaddir = true;              /* Do we have to reload the directory file list? */
1.1       root      465:        int retbut;
                    466:        int oldcursorstate;
1.1.1.9 ! root      467:        int selection;                      /* The selection index */
1.1       root      468:        char *zipfilename;                  /* Filename in zip file */
                    469:        char *zipdir;
1.1.1.7   root      470:        bool browsingzip = false;           /* Are we browsing an archive? */
1.1       root      471:        zip_dir *zipfiles = NULL;
1.1.1.2   root      472:        SDL_Event sdlEvent;
1.1.1.9 ! root      473:        int yScrolbar_size;                             /* Size of the vertical scrollbar */
1.1.1.2   root      474: 
                    475:        ypos = 0;
1.1.1.9 ! root      476:        scrollbar_Ypos = 0.0;
1.1.1.7   root      477:        refreshentries = true;
1.1.1.2   root      478:        entries = 0;
1.1       root      479: 
                    480:        /* Allocate memory for the file and path name strings: */
                    481:        pStringMem = malloc(4 * FILENAME_MAX);
                    482:        path = pStringMem;
                    483:        fname = pStringMem + FILENAME_MAX;
1.1.1.4   root      484:        zipdir = pStringMem + 2 * FILENAME_MAX;
                    485:        zipfilename = pStringMem + 3 * FILENAME_MAX;
1.1       root      486:        zipfilename[0] = 0;
1.1.1.5   root      487:        fname[0] = 0;
                    488:        path[0] = 0;
1.1       root      489: 
                    490:        SDLGui_CenterDlg(fsdlg);
                    491:        if (bAllowNew)
                    492:        {
                    493:                fsdlg[SGFSDLG_FILENAME].type = SGEDITFIELD;
                    494:                fsdlg[SGFSDLG_FILENAME].flags |= SG_EXIT;
                    495:        }
                    496:        else
                    497:        {
                    498:                fsdlg[SGFSDLG_FILENAME].type = SGTEXT;
                    499:                fsdlg[SGFSDLG_FILENAME].flags &= ~SG_EXIT;
                    500:        }
                    501: 
                    502:        /* Prepare the path and filename variables */
1.1.1.4   root      503:        if (path_and_name && path_and_name[0])
1.1.1.2   root      504:        {
1.1.1.4   root      505:                strncpy(path, path_and_name, FILENAME_MAX);
                    506:                path[FILENAME_MAX-1] = '\0';
                    507:        }
1.1.1.5   root      508:        if (!File_DirExists(path))
1.1.1.4   root      509:        {
1.1.1.5   root      510:                File_SplitPath(path, path, fname, NULL);
                    511:                if (!(File_DirExists(path) || getcwd(path, FILENAME_MAX)))
1.1.1.4   root      512:                {
1.1.1.5   root      513:                        perror("SDLGui_FileSelect: non-existing path and CWD failed");
1.1.1.8   root      514:                        free(pStringMem);
1.1.1.4   root      515:                        return NULL;
                    516:                }
1.1.1.2   root      517:        }
1.1.1.5   root      518: 
1.1.1.2   root      519:        File_MakeAbsoluteName(path);
                    520:        File_MakeValidPathName(path);
1.1       root      521:        File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
                    522:        File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
                    523: 
1.1.1.4   root      524:        /* Save old mouse cursor state and enable cursor */
1.1       root      525:        oldcursorstate = SDL_ShowCursor(SDL_QUERY);
                    526:        if (oldcursorstate == SDL_DISABLE)
                    527:                SDL_ShowCursor(SDL_ENABLE);
                    528: 
                    529:        do
                    530:        {
                    531:                if (reloaddir)
                    532:                {
1.1.1.4   root      533:                        files = files_free(files);
1.1       root      534: 
                    535:                        if (browsingzip)
                    536:                        {
                    537:                                files = ZIP_GetFilesDir(zipfiles, zipdir, &entries);
1.1.1.8   root      538:                                if(!files)
                    539:                                {
                    540:                                        fprintf(stderr, "SDLGui_FileSelect: ZIP_GetFilesDir error!\n");
                    541:                                        free(pStringMem);
                    542:                                        return NULL;
                    543:                                }
1.1       root      544:                        }
                    545:                        else
                    546:                        {
                    547:                                /* Load directory entries: */
                    548:                                entries = scandir(path, &files, 0, alphasort);
                    549:                        }
1.1.1.3   root      550:                        
                    551:                        /* Remove hidden files from the list if necessary: */
                    552:                        if (!(fsdlg[SGFSDLG_SHOWHIDDEN].state & SG_SELECTED))
                    553:                        {
                    554:                                DlgFileSelect_RemoveHiddenFiles(files);
                    555:                        }
1.1       root      556: 
                    557:                        if (entries < 0)
                    558:                        {
                    559:                                fprintf(stderr, "SDLGui_FileSelect: Path not found.\n");
                    560:                                free(pStringMem);
1.1.1.5   root      561:                                return NULL;
1.1       root      562:                        }
                    563: 
1.1.1.4   root      564:                        /* reload always implies refresh */
1.1.1.7   root      565:                        reloaddir = false;
                    566:                        refreshentries = true;
1.1       root      567:                }/* reloaddir */
                    568: 
1.1.1.9 ! root      569:                /* Refresh scrollbar size */
        !           570:                if (entries <= SGFS_NUMENTRIES)
        !           571:                        yScrolbar_size = (SGFS_NUMENTRIES-2) * sdlgui_fontheight;
        !           572:                else
        !           573:                        yScrolbar_size = (int)((SGFS_NUMENTRIES-2) / ((float)entries/(float)SGFS_NUMENTRIES) * sdlgui_fontheight);
        !           574:                fsdlg[SGFSDLG_SCROLLBAR].w = yScrolbar_size;
        !           575:                
        !           576:                /* Refresh scrolbar pos */
        !           577:                fsdlg[SGFSDLG_SCROLLBAR].h = (int) (scrollbar_Ypos * sdlgui_fontheight);
        !           578:                ypos = (int) (scrollbar_Ypos * ((float)entries/(float)(SGFS_NUMENTRIES-2)) + 0.5);
        !           579:                
1.1       root      580:                /* Update the file name strings in the dialog? */
                    581:                if (refreshentries)
                    582:                {
1.1.1.2   root      583:                        if (!DlgFileSelect_RefreshEntries(files, path, browsingzip))
1.1       root      584:                        {
                    585:                                free(pStringMem);
1.1.1.5   root      586:                                return NULL;
1.1       root      587:                        }
1.1.1.7   root      588:                        refreshentries = false;
1.1       root      589:                }
                    590: 
                    591:                /* Show dialog: */
1.1.1.2   root      592:                retbut = SDLGui_DoDialog(fsdlg, &sdlEvent);
1.1       root      593: 
                    594:                /* Has the user clicked on a file or folder? */
1.1.1.9 ! root      595:                if (retbut>=SGFSDLG_ENTRYFIRST && retbut<=SGFSDLG_ENTRYLAST && retbut-SGFSDLG_ENTRYFIRST+ypos<entries)
1.1       root      596:                {
                    597:                        char *tempstr;
1.1.1.4   root      598:                        
1.1       root      599:                        tempstr = malloc(FILENAME_MAX);
                    600:                        if (!tempstr)
                    601:                        {
                    602:                                perror("Error while allocating temporary memory in SDLGui_FileSelect()");
                    603:                                free(pStringMem);
1.1.1.5   root      604:                                return NULL;
1.1       root      605:                        }
                    606: 
1.1.1.7   root      607:                        if (browsingzip == true)
1.1       root      608:                        {
1.1.1.4   root      609:                                if (!strcat_maxlen(tempstr, FILENAME_MAX,
1.1.1.9 ! root      610:                                                   zipdir, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name))
1.1.1.4   root      611:                                {
                    612:                                        fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
                    613:                                        free(pStringMem);
1.1.1.5   root      614:                                        return NULL;
1.1.1.4   root      615:                                }
                    616:                                /* directory? */
1.1.1.3   root      617:                                if (File_DoesFileNameEndWithSlash(tempstr))
1.1       root      618:                                {
                    619:                                        /* handle the ../ directory */
1.1.1.9 ! root      620:                                        if (strcmp(files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name, "../") == 0)
1.1       root      621:                                        {
                    622:                                                /* close the zip file */
1.1.1.4   root      623:                                                if (strcmp(tempstr, "../") == 0)
1.1       root      624:                                                {
                    625:                                                        /* free zip file entries */
                    626:                                                        ZIP_FreeZipDir(zipfiles);
                    627:                                                        zipfiles = NULL;
                    628:                                                        /* Copy the path name to the dialog */
                    629:                                                        File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
1.1.1.7   root      630:                                                        browsingzip = false;
1.1       root      631:                                                }
                    632:                                                else
                    633:                                                {
1.1.1.4   root      634:                                                        /* remove "../" and previous dir from path */
                    635:                                                        File_PathShorten(tempstr, 2);
                    636:                                                        correct_zip_root(tempstr);
1.1       root      637:                                                        strcpy(zipdir, tempstr);
                    638:                                                        File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
                    639:                                                }
                    640:                                        }
                    641:                                        else /* not the "../" directory */
                    642:                                        {
                    643:                                                strcpy(zipdir, tempstr);
                    644:                                                File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
                    645:                                        }
1.1.1.7   root      646:                                        reloaddir = true;
1.1       root      647:                                        /* Copy the path name to the dialog */
                    648:                                        zipfilename[0] = '\0';
                    649:                                        dlgfname[0] = 0;
                    650:                                        ypos = 0;
1.1.1.9 ! root      651:                                        scrollbar_Ypos = 0.0;
1.1       root      652:                                }
                    653:                                else
                    654:                                {
1.1.1.4   root      655:                                        /* not dir, select a file in the zip */
1.1.1.9 ! root      656:                                        selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
1.1       root      657:                                        strcpy(zipfilename, files[selection]->d_name);
                    658:                                        File_ShrinkName(dlgfname, zipfilename, DLGFNAME_SIZE);
                    659:                                }
                    660: 
1.1.1.4   root      661:                        }
                    662:                        else /* not browsingzip */
1.1       root      663:                        {
1.1.1.4   root      664:                                if (!strcat_maxlen(tempstr, FILENAME_MAX,
1.1.1.9 ! root      665:                                                   path, files[retbut-SGFSDLG_ENTRYFIRST+ypos]->d_name))
1.1       root      666:                                {
1.1.1.4   root      667:                                        fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
                    668:                                        free(pStringMem);
1.1.1.5   root      669:                                        return NULL;
1.1.1.4   root      670:                                }
1.1.1.5   root      671:                                if (File_DirExists(tempstr))
1.1.1.4   root      672:                                {
                    673:                                        File_HandleDotDirs(tempstr);
                    674:                                        File_AddSlashToEndFileName(tempstr);
                    675:                                        /* Copy the path name to the dialog */
                    676:                                        File_ShrinkName(dlgpath, tempstr, DLGPATH_SIZE);
1.1       root      677:                                        strcpy(path, tempstr);
1.1.1.7   root      678:                                        reloaddir = true;
1.1       root      679:                                        dlgfname[0] = 0;
                    680:                                        ypos = 0;
1.1.1.9 ! root      681:                                        scrollbar_Ypos = 0.0;
1.1       root      682:                                }
                    683:                                else if (ZIP_FileNameIsZIP(tempstr) && zip_path != NULL)
                    684:                                {
                    685:                                        /* open a zip file */
                    686:                                        zipfiles = ZIP_GetFiles(tempstr);
1.1.1.7   root      687:                                        if (zipfiles != NULL && browsingzip == false)
1.1       root      688:                                        {
1.1.1.9 ! root      689:                                                selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
1.1       root      690:                                                strcpy(fname, files[selection]->d_name);
                    691:                                                File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
1.1.1.7   root      692:                                                browsingzip = true;
1.1.1.4   root      693:                                                zipdir[0] = '\0'; /* zip root */
1.1       root      694:                                                File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
1.1.1.7   root      695:                                                reloaddir = true;
1.1       root      696:                                                ypos = 0;
1.1.1.9 ! root      697:                                                scrollbar_Ypos = 0.0;
1.1       root      698:                                        }
                    699: 
                    700:                                }
                    701:                                else
                    702:                                {
                    703:                                        /* Select a file */
1.1.1.9 ! root      704:                                        selection = retbut-SGFSDLG_ENTRYFIRST+ypos;
1.1       root      705:                                        strcpy(fname, files[selection]->d_name);
                    706:                                        File_ShrinkName(dlgfname, fname, DLGFNAME_SIZE);
                    707:                                }
                    708: 
                    709:                        } /* not browsingzip */
                    710: 
                    711:                        free(tempstr);
                    712:                }
                    713:                else    /* Has the user clicked on another button? */
                    714:                {
                    715:                        switch(retbut)
                    716:                        {
                    717:                        case SGFSDLG_UPDIR:                 /* Change path to parent directory */
1.1.1.4   root      718:                                if (browsingzip)
1.1       root      719:                                {
1.1.1.4   root      720:                                        /* close the zip file? */
                    721:                                        if (!zipdir[0])
1.1       root      722:                                        {
                    723:                                                /* free zip file entries */
                    724:                                                ZIP_FreeZipDir(zipfiles);
1.1.1.7   root      725:                                                browsingzip = false;
1.1       root      726:                                                zipfiles = NULL;
                    727:                                                File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
                    728:                                        }
                    729:                                        else
                    730:                                        {
1.1.1.4   root      731:                                                /* remove last dir from zipdir path */
                    732:                                                File_PathShorten(zipdir, 1);
                    733:                                                correct_zip_root(zipdir);
1.1       root      734:                                                File_ShrinkName(dlgpath, zipdir, DLGPATH_SIZE);
                    735:                                                zipfilename[0] = '\0';
                    736:                                        }
                    737:                                }  /* not a zip file: */
1.1.1.4   root      738:                                else
1.1       root      739:                                {
1.1.1.4   root      740:                                        File_PathShorten(path, 1);
                    741:                                        File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
1.1       root      742:                                }
1.1.1.7   root      743:                                reloaddir = true;
1.1       root      744:                                break;
1.1.1.3   root      745: 
                    746:                        case SGFSDLG_HOMEDIR:               /* Change to home directory */
1.1.1.8   root      747:                                home = Paths_GetUserHome();
                    748:                                if (home == NULL || !*home)
1.1.1.3   root      749:                                        break;
                    750:                                if (browsingzip)
                    751:                                {
                    752:                                        /* free zip file entries */
                    753:                                        ZIP_FreeZipDir(zipfiles);
                    754:                                        zipfiles = NULL;
1.1.1.7   root      755:                                        browsingzip = false;
1.1.1.3   root      756:                                }
1.1.1.4   root      757:                                strcpy(path, home);
1.1.1.3   root      758:                                File_AddSlashToEndFileName(path);
1.1.1.4   root      759:                                File_ShrinkName(dlgpath, path, DLGPATH_SIZE);
1.1.1.7   root      760:                                reloaddir = true;
1.1.1.3   root      761:                                break;
                    762: 
1.1       root      763:                        case SGFSDLG_ROOTDIR:               /* Change to root directory */
1.1.1.4   root      764:                                if (browsingzip)
1.1       root      765:                                {
                    766:                                        /* free zip file entries */
                    767:                                        ZIP_FreeZipDir(zipfiles);
                    768:                                        zipfiles = NULL;
1.1.1.7   root      769:                                        browsingzip = false;
1.1       root      770:                                }
1.1.1.7   root      771:                                path[0] = PATHSEP; path[1] = '\0';
1.1       root      772:                                strcpy(dlgpath, path);
1.1.1.7   root      773:                                reloaddir = true;
1.1       root      774:                                break;
                    775:                        case SGFSDLG_UP:                    /* Scroll up */
1.1.1.2   root      776:                                DlgFileSelect_ScrollUp();
                    777:                                SDL_Delay(10);
1.1       root      778:                                break;
                    779:                        case SGFSDLG_DOWN:                  /* Scroll down */
1.1.1.2   root      780:                                DlgFileSelect_ScrollDown();
                    781:                                SDL_Delay(10);
1.1       root      782:                                break;
1.1.1.9 ! root      783:                        case SGFSDLG_SCROLLBAR:             /* Scrollbar selected */
        !           784:                                DlgFileSelect_ManageScrollbar();
        !           785:                                SDL_Delay(10);
        !           786:                                break;
1.1       root      787:                        case SGFSDLG_FILENAME:              /* User entered new filename */
                    788:                                strcpy(fname, dlgfname);
                    789:                                break;
1.1.1.3   root      790:                        case SGFSDLG_SHOWHIDDEN:            /* Show/hide hidden files */
1.1.1.7   root      791:                                reloaddir = true;
1.1.1.3   root      792:                                ypos = 0;
1.1.1.9 ! root      793:                                scrollbar_Ypos = 0.0;
1.1.1.3   root      794:                                break;
1.1.1.2   root      795:                        case SDLGUI_UNKNOWNEVENT:
                    796:                                DlgFileSelect_HandleSdlEvents(&sdlEvent);
                    797:                                break;
1.1       root      798:                        } /* switch */
1.1.1.4   root      799:       
                    800:                        if (reloaddir)
                    801:                        {
                    802:                                /* Remove old selection */
                    803:                                fname[0] = 0;
                    804:                                dlgfname[0] = 0;
                    805:                                ypos = 0;
1.1.1.9 ! root      806:                                scrollbar_Ypos = 0.0;
1.1.1.4   root      807:                        }
1.1       root      808:                } /* other button code */
                    809: 
                    810: 
                    811:        } /* do */
1.1.1.4   root      812:        while (retbut!=SGFSDLG_OKAY && retbut!=SGFSDLG_CANCEL
                    813:               && retbut!=SDLGUI_QUIT && retbut != SDLGUI_ERROR && !bQuitProgram);
1.1       root      814: 
                    815:        if (oldcursorstate == SDL_DISABLE)
                    816:                SDL_ShowCursor(SDL_DISABLE);
                    817: 
1.1.1.4   root      818:        files_free(files);
1.1       root      819: 
                    820:        if (browsingzip)
                    821:        {
                    822:                /* free zip file entries */
                    823:                ZIP_FreeZipDir(zipfiles);
                    824:                zipfiles = NULL;
                    825:        }
                    826: 
1.1.1.4   root      827:        if (retbut == SGFSDLG_OKAY)
1.1       root      828:        {
1.1.1.4   root      829:                if (zip_path)
                    830:                        *zip_path = zip_get_path(zipdir, zipfilename, browsingzip);
                    831:                retpath = File_MakePath(path, fname, NULL);
                    832:        }
                    833:        else
                    834:                retpath = NULL;
                    835:        free(pStringMem);
                    836:        return retpath;
                    837: }
                    838: 
                    839: 
                    840: /*-----------------------------------------------------------------------*/
1.1.1.8   root      841: /**
                    842:  * Let user browse for a file, confname is used as default.
1.1.1.4   root      843:  * If bAllowNew is true, user can select new files also.
                    844:  * 
                    845:  * If no file is selected, or there's some problem with the file,
1.1.1.7   root      846:  * return false and clear dlgname & confname.
                    847:  * Otherwise return true, set dlgname & confname to the new file name
1.1.1.4   root      848:  * (dlgname is shrinked & limited to maxlen and confname is assumed
                    849:  * to have FILENAME_MAX amount of space).
                    850:  */
1.1.1.5   root      851: bool SDLGui_FileConfSelect(char *dlgname, char *confname, int maxlen, bool bAllowNew)
1.1.1.4   root      852: {
                    853:        char *selname;
                    854:        
                    855:        selname = SDLGui_FileSelect(confname, NULL, bAllowNew);
                    856:        if (selname)
                    857:        {
                    858:                if (!File_DoesFileNameEndWithSlash(selname) &&
                    859:                    (bAllowNew || File_Exists(selname)))
1.1       root      860:                {
1.1.1.4   root      861:                        strncpy(confname, selname, FILENAME_MAX);
                    862:                        confname[FILENAME_MAX-1] = '\0';
                    863:                        File_ShrinkName(dlgname, selname, maxlen);
1.1       root      864:                }
                    865:                else
1.1.1.4   root      866:                {
                    867:                        dlgname[0] = confname[0] = 0;
                    868:                }
                    869:                free(selname);
1.1.1.7   root      870:                return true;
1.1       root      871:        }
1.1.1.7   root      872:        return false;
1.1       root      873: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.