Annotation of previous/src/gui-sdl/dlgDiskSelect.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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