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