|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.