|
|
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: */
1.1.1.2 ! root 459: static char* SDLGui_DiskSelectDialog(const char *path_and_name, char **zip_path, bool *readonly)
1.1 root 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.