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