Annotation of previous/src/gui-sdl/dlgDiskSelect.c, revision 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.