|
|
1.1 root 1: /*
2: Hatari - sdlgui.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 tiny graphical user interface for Hatari.
8: */
9:
10: #include <SDL.h>
11: #include <sys/stat.h>
12: #include <unistd.h>
13: #include <dirent.h>
14:
15: #include "main.h"
16: #include "memAlloc.h"
17: #include "screen.h"
18: #include "sdlgui.h"
19: #include "file.h"
20:
21: #define SGRADIOBUTTON_NORMAL 12
22: #define SGRADIOBUTTON_SELECTED 13
23: #define SGCHECKBOX_NORMAL 14
24: #define SGCHECKBOX_SELECTED 15
25: #define SGARROWUP 1
26: #define SGARROWDOWN 2
27: #define SGFOLDER 5
28:
29:
30:
31: static SDL_Surface *stdfontgfx = NULL; /* The 'standard' font graphics */
32: static SDL_Surface *fontgfx = NULL; /* The actual font graphics */
33: static int fontwidth, fontheight; /* Height and width of the actual font */
34:
35:
36:
37: /*-----------------------------------------------------------------------*/
38: /*
39: Initialize the GUI.
40: */
41: int SDLGui_Init()
42: {
43: const char *fontname = "font8.bmp";
44:
45: /* Load the font graphics: */
46: stdfontgfx = SDL_LoadBMP(fontname);
47: if( stdfontgfx==NULL )
48: {
49: fprintf(stderr, "Error: Can't load image %s: %s\n", fontname, SDL_GetError() );
50: return -1;
51: }
52:
53: return 0;
54: }
55:
56:
57: /*-----------------------------------------------------------------------*/
58: /*
59: Uninitialize the GUI.
60: */
61: int SDLGui_UnInit()
62: {
63: if(stdfontgfx)
64: {
65: SDL_FreeSurface(stdfontgfx);
66: stdfontgfx = NULL;
67: }
68: if(fontgfx)
69: {
70: SDL_FreeSurface(fontgfx);
71: fontgfx = NULL;
72: }
73:
74: return 0;
75: }
76:
77:
78: /*-----------------------------------------------------------------------*/
79: /*
80: Prepare the font to suit the actual resolution.
81: */
82: int SDLGui_PrepareFont()
83: {
84: /* FIXME: Freeing the old font gfx does sometimes crash with a SEGFAULT
85: if(fontgfx)
86: {
87: SDL_FreeSurface(fontgfx);
88: fontgfx = NULL;
89: }
90: */
91:
92: if( stdfontgfx==NULL )
93: {
94: fprintf(stderr, "Error: The font has not been loaded!\n");
95: return -1;
96: }
97:
98: /* Convert the font graphics to the actual screen format */
99: fontgfx = SDL_DisplayFormat(stdfontgfx);
100: if( fontgfx==NULL )
101: {
102: fprintf(stderr, "Could not convert font:\n %s\n", SDL_GetError() );
103: return -1;
104: }
105: /* Set transparent pixel */
106: SDL_SetColorKey(fontgfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), SDL_MapRGB(fontgfx->format,255,255,255));
107: /* Get the font width and height: */
108: fontwidth = fontgfx->w/16;
109: fontheight = fontgfx->h/16;
110:
111: return 0;
112: }
113:
114:
115: /*-----------------------------------------------------------------------*/
116: /*
117: Center a dialog so that it appears in the middle of the screen.
118: Note: We only store the coordinates in the root box of the dialog,
119: all other objects in the dialog are positioned relatively to this one.
120: */
121: void SDLGui_CenterDlg(SGOBJ *dlg)
122: {
123: dlg[0].x = (sdlscrn->w/fontwidth-dlg[0].w)/2;
124: dlg[0].y = (sdlscrn->h/fontheight-dlg[0].h)/2;
125: }
126:
127:
128: /*-----------------------------------------------------------------------*/
129: /*
130: Draw a text string.
131: */
132: void SDLGui_Text(int x, int y, const char *txt)
133: {
134: int i;
135: char c;
136: SDL_Rect sr, dr;
137:
138: for(i=0; txt[i]!=0; i++)
139: {
140: c = txt[i];
141: sr.x=fontwidth*(c%16); sr.y=fontheight*(c/16);
142: sr.w=fontwidth; sr.h=fontheight;
143: dr.x=x+i*fontwidth; dr.y=y;
144: dr.w=fontwidth; dr.h=fontheight;
145: SDL_BlitSurface(fontgfx, &sr, sdlscrn, &dr);
146: }
147: }
148:
149:
150: /*-----------------------------------------------------------------------*/
151: /*
152: Draw a dialog text object.
153: */
154: void SDLGui_DrawText(SGOBJ *tdlg, int objnum)
155: {
156: int x, y;
157: x = (tdlg[0].x+tdlg[objnum].x)*fontwidth;
158: y = (tdlg[0].y+tdlg[objnum].y)*fontheight;
159: SDLGui_Text(x, y, tdlg[objnum].txt);
160: }
161:
162:
163: /*-----------------------------------------------------------------------*/
164: /*
165: Draw a dialog box object.
166: */
167: void SDLGui_DrawBox(SGOBJ *bdlg, int objnum)
168: {
169: SDL_Rect rect;
170: int x, y, w, h;
171: Uint32 grey = SDL_MapRGB(sdlscrn->format,192,192,192);
172: Uint32 upleftc, downrightc;
173:
174: x = bdlg[objnum].x*fontwidth;
175: y = bdlg[objnum].y*fontheight;
176: if(objnum>0) /* Since the root object is a box, too, */
177: { /* we have to look for it now here and only */
178: x += bdlg[0].x*fontwidth; /* add its absolute coordinates if we need to */
179: y += bdlg[0].y*fontheight;
180: }
181: w = bdlg[objnum].w*fontwidth;
182: h = bdlg[objnum].h*fontheight;
183:
184: if( bdlg[objnum].state&SG_SELECTED )
185: {
186: upleftc = SDL_MapRGB(sdlscrn->format,128,128,128);
187: downrightc = SDL_MapRGB(sdlscrn->format,255,255,255);
188: }
189: else
190: {
191: upleftc = SDL_MapRGB(sdlscrn->format,255,255,255);
192: downrightc = SDL_MapRGB(sdlscrn->format,128,128,128);
193: }
194:
195: rect.x = x; rect.y = y;
196: rect.w = w; rect.h = h;
197: SDL_FillRect(sdlscrn, &rect, grey);
198:
199: rect.x = x; rect.y = y-1;
200: rect.w = w; rect.h = 1;
201: SDL_FillRect(sdlscrn, &rect, upleftc);
202:
203: rect.x = x-1; rect.y = y;
204: rect.w = 1; rect.h = h;
205: SDL_FillRect(sdlscrn, &rect, upleftc);
206:
207: rect.x = x; rect.y = y+h;
208: rect.w = w; rect.h = 1;
209: SDL_FillRect(sdlscrn, &rect, downrightc);
210:
211: rect.x = x+w; rect.y = y;
212: rect.w = 1; rect.h = h;
213: SDL_FillRect(sdlscrn, &rect, downrightc);
214: }
215:
216:
217: /*-----------------------------------------------------------------------*/
218: /*
219: Draw a normal button.
220: */
221: void SDLGui_DrawButton(SGOBJ *bdlg, int objnum)
222: {
223: int x,y;
224:
225: SDLGui_DrawBox(bdlg, objnum);
226:
227: x = (bdlg[0].x+bdlg[objnum].x+(bdlg[objnum].w-strlen(bdlg[objnum].txt))/2)*fontwidth;
228: y = (bdlg[0].y+bdlg[objnum].y+(bdlg[objnum].h-1)/2)*fontheight;
229:
230: if( bdlg[objnum].state&SG_SELECTED )
231: {
232: x+=1;
233: y+=1;
234: }
235: SDLGui_Text(x, y, bdlg[objnum].txt);
236: }
237:
238:
239: /*-----------------------------------------------------------------------*/
240: /*
241: Draw a dialog radio button object.
242: */
243: void SDLGui_DrawRadioButton(SGOBJ *rdlg, int objnum)
244: {
245: char str[80];
246: int x, y;
247:
248: x = (rdlg[0].x+rdlg[objnum].x)*fontwidth;
249: y = (rdlg[0].y+rdlg[objnum].y)*fontheight;
250:
251: if( rdlg[objnum].state&SG_SELECTED )
252: str[0]=SGRADIOBUTTON_SELECTED;
253: else
254: str[0]=SGRADIOBUTTON_NORMAL;
255: str[1]=' ';
256: strcpy(&str[2], rdlg[objnum].txt);
257:
258: SDLGui_Text(x, y, str);
259: }
260:
261:
262: /*-----------------------------------------------------------------------*/
263: /*
264: Draw a dialog check box object.
265: */
266: void SDLGui_DrawCheckBox(SGOBJ *cdlg, int objnum)
267: {
268: char str[80];
269: int x, y;
270:
271: x = (cdlg[0].x+cdlg[objnum].x)*fontwidth;
272: y = (cdlg[0].y+cdlg[objnum].y)*fontheight;
273:
274: if( cdlg[objnum].state&SG_SELECTED )
275: str[0]=SGCHECKBOX_SELECTED;
276: else
277: str[0]=SGCHECKBOX_NORMAL;
278: str[1]=' ';
279: strcpy(&str[2], cdlg[objnum].txt);
280:
281: SDLGui_Text(x, y, str);
282: }
283:
284:
285: /*-----------------------------------------------------------------------*/
286: /*
287: Draw a dialog popup button object.
288: */
289: void SDLGui_DrawPopupButton(SGOBJ *pdlg, int objnum)
290: {
291: int x, y, w, h;
292: const char *downstr = "\x02";
293:
294: SDLGui_DrawBox(pdlg, objnum);
295:
296: x = (pdlg[0].x+pdlg[objnum].x)*fontwidth;
297: y = (pdlg[0].y+pdlg[objnum].y)*fontheight;
298: w = pdlg[objnum].w*fontwidth;
299: h = pdlg[objnum].h*fontheight;
300:
301: SDLGui_Text(x, y, pdlg[objnum].txt);
302: SDLGui_Text(x+w-fontwidth, y, downstr);
303: }
304:
305:
306: /*-----------------------------------------------------------------------*/
307: /*
308: Draw a whole dialog.
309: */
310: void SDLGui_DrawDialog(SGOBJ *dlg)
311: {
312: int i;
313: for(i=0; dlg[i].type!=-1; i++ )
314: {
315: switch( dlg[i].type )
316: {
317: case SGBOX:
318: SDLGui_DrawBox(dlg, i);
319: break;
320: case SGTEXT:
321: SDLGui_DrawText(dlg, i);
322: break;
323: case SGBUTTON:
324: SDLGui_DrawButton(dlg, i);
325: break;
326: case SGRADIOBUT:
327: SDLGui_DrawRadioButton(dlg, i);
328: break;
329: case SGCHECKBOX:
330: SDLGui_DrawCheckBox(dlg, i);
331: break;
332: case SGPOPUP:
333: SDLGui_DrawPopupButton(dlg, i);
334: break;
335: }
336: }
337: SDL_UpdateRect(sdlscrn, 0,0,0,0);
338: }
339:
340:
341: /*-----------------------------------------------------------------------*/
342: /*
343: Search an object at a certain position.
344: */
345: int SDLGui_FindObj(SGOBJ *dlg, int fx, int fy)
346: {
347: int len, i;
348: int ob = -1;
349: int xpos, ypos;
350:
351: len = 0;
352: while( dlg[len].type!=-1) len++;
353:
354: xpos = fx/fontwidth;
355: ypos = fy/fontheight;
356: /* Now search for the object: */
357: for(i=len; i>0; i--)
358: {
359: if(xpos>=dlg[0].x+dlg[i].x && ypos>=dlg[0].y+dlg[i].y
360: && xpos<dlg[0].x+dlg[i].x+dlg[i].w && ypos<dlg[0].y+dlg[i].y+dlg[i].h)
361: {
362: ob = i;
363: break;
364: }
365: }
366:
367: return ob;
368: }
369:
370:
371: /*-----------------------------------------------------------------------*/
372: /*
373: Show and process a dialog. Returns the button number that has been
374: pressed or -1 if something went wrong.
375: */
376: int SDLGui_DoDialog(SGOBJ *dlg)
377: {
378: int obj=0;
379: int oldbutton=0;
380: int retbutton=0;
381: int i, j, b;
382: SDL_Event evnt;
383: SDL_Rect rct;
384: Uint32 grey;
385:
386: grey = SDL_MapRGB(sdlscrn->format,192,192,192);
387:
388: SDLGui_DrawDialog(dlg);
389:
390: /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
391: SDL_PumpEvents();
392: b = SDL_GetMouseState(&i, &j);
393: obj = SDLGui_FindObj(dlg, i, j);
394: if(obj>0 && (dlg[obj].flags&SG_TOUCHEXIT) )
395: {
396: oldbutton = obj;
397: if( b&SDL_BUTTON(1) )
398: {
399: dlg[obj].state |= SG_SELECTED;
400: return obj;
401: }
402: }
403:
404: /* The main loop */
405: do
406: {
407: if( SDL_WaitEvent(&evnt)==1 ) /* Wait for events */
408: switch(evnt.type)
409: {
410: case SDL_KEYDOWN:
411: break;
412: case SDL_QUIT:
413: bQuitProgram = TRUE;
414: break;
415: case SDL_MOUSEBUTTONDOWN:
416: obj = SDLGui_FindObj(dlg, evnt.button.x, evnt.button.y);
417: if(obj>0)
418: {
419: if(dlg[obj].type==SGBUTTON)
420: {
421: dlg[obj].state |= SG_SELECTED;
422: SDLGui_DrawButton(dlg, obj);
423: SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
424: dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
425: oldbutton=obj;
426: }
427: if( dlg[obj].flags&SG_TOUCHEXIT )
428: {
429: dlg[obj].state |= SG_SELECTED;
430: retbutton = obj;
431: }
432: }
433: break;
434: case SDL_MOUSEBUTTONUP:
435: obj = SDLGui_FindObj(dlg, evnt.button.x, evnt.button.y);
436: if(obj>0)
437: {
438: switch(dlg[obj].type)
439: {
440: case SGBUTTON:
441: if(oldbutton==obj)
442: retbutton=obj;
443: break;
444: case SGRADIOBUT:
445: for(i=obj-1; i>0 && dlg[i].type==SGRADIOBUT; i--)
446: {
447: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
448: rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
449: rct.y = (dlg[0].y+dlg[i].y)*fontheight;
450: rct.w = fontwidth; rct.h = fontheight;
451: SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
452: SDLGui_DrawRadioButton(dlg, i);
453: SDL_UpdateRects(sdlscrn, 1, &rct);
454: }
455: for(i=obj+1; dlg[i].type==SGRADIOBUT; i++)
456: {
457: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
458: rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
459: rct.y = (dlg[0].y+dlg[i].y)*fontheight;
460: rct.w = fontwidth; rct.h = fontheight;
461: SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
462: SDLGui_DrawRadioButton(dlg, i);
463: SDL_UpdateRects(sdlscrn, 1, &rct);
464: }
465: dlg[obj].state |= SG_SELECTED; /* Select this radio button */
466: rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
467: rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
468: rct.w = fontwidth; rct.h = fontheight;
469: SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
470: SDLGui_DrawRadioButton(dlg, obj);
471: SDL_UpdateRects(sdlscrn, 1, &rct);
472: break;
473: case SGCHECKBOX:
474: dlg[obj].state ^= SG_SELECTED;
475: rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
476: rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
477: rct.w = fontwidth; rct.h = fontheight;
478: SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
479: SDLGui_DrawCheckBox(dlg, obj);
480: SDL_UpdateRects(sdlscrn, 1, &rct);
481: break;
482: case SGPOPUP:
483: dlg[obj].state |= SG_SELECTED;
484: SDLGui_DrawPopupButton(dlg, obj);
485: SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
486: dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
487: retbutton=obj;
488: break;
489: }
490: }
491: if(oldbutton>0)
492: {
493: dlg[oldbutton].state &= ~SG_SELECTED;
494: SDLGui_DrawButton(dlg, oldbutton);
495: SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[oldbutton].x)*fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*fontheight-2,
496: dlg[oldbutton].w*fontwidth+4, dlg[oldbutton].h*fontheight+4);
497: oldbutton = 0;
498: }
499: if( dlg[obj].flags&SG_EXIT )
500: {
501: retbutton = obj;
502: }
503: break;
504: }
505: }
506: while(retbutton==0 && !bQuitProgram);
507:
508: if(bQuitProgram)
509: retbutton=-1;
510:
511: return retbutton;
512: }
513:
514:
515: /*-----------------------------------------------------------------------*/
516: /*
517: Show and process a file select dialog.
518: Returns TRUE if the use selected "okay", FALSE if "cancel".
519: input: zip_path = pointer to buffer to contain file path within a selected
520: zip file, or NULL if browsing zip files is disallowed.
521: */
522: #define SGFSDLG_UPDIR 6
523: #define SGFSDLG_ROOTDIR 7
524: #define SGFSDLG_ENTRY1 10
525: #define SGFSDLG_ENTRY16 25
526: #define SGFSDLG_UP 26
527: #define SGFSDLG_DOWN 27
528: #define SGFSDLG_OKAY 28
529: #define SGFSDLG_CANCEL 29
530: int SDLGui_FileSelect(char *path_and_name, char *zip_path)
531: {
532: int i,n;
533: int entries = 0; /* How many files are in the actual directory? */
534: int ypos = 0;
535: char dlgfilenames[16][36];
536: struct dirent **files = NULL;
537: char path[MAX_FILENAME_LENGTH], fname[128]; /* The actual file and path names */
538: char dlgpath[39], dlgfname[33]; /* File and path name in the dialog */
539: BOOL reloaddir = TRUE; /* Do we have to reload the directory file list? */
540: BOOL refreshentries = TRUE; /* Do we have to update the file names in the dialog? */
541: int retbut;
542: int oldcursorstate;
543: int selection = -1; /* The actual selection, -1 if none selected */
544: char zipfilename[MAX_FILENAME_LENGTH]; /* Filename in zip file */
545: char zipdir[MAX_FILENAME_LENGTH];
546: BOOL browsingzip = FALSE; /* Are we browsing an archive? */
547:
548: SGOBJ fsdlg[] =
549: {
550: { SGBOX, 0, 0, 0,0, 40,25, NULL },
551: { SGTEXT, 0, 0, 13,1, 13,1, "Choose a file" },
552: { SGTEXT, 0, 0, 1,2, 7,1, "Folder:" },
553: { SGTEXT, 0, 0, 1,3, 38,1, dlgpath },
554: { SGTEXT, 0, 0, 1,4, 6,1, "File:" },
555: { SGTEXT, 0, 0, 7,4, 31,1, dlgfname },
556: { SGBUTTON, 0, 0, 31,1, 4,1, ".." },
557: { SGBUTTON, 0, 0, 36,1, 3,1, "/" },
558: { SGBOX, 0, 0, 1,6, 38,16, NULL },
559: { SGBOX, 0, 0, 38,7, 1,14, NULL },
560: { SGTEXT, SG_EXIT, 0, 2,6, 35,1, dlgfilenames[0] },
561: { SGTEXT, SG_EXIT, 0, 2,7, 35,1, dlgfilenames[1] },
562: { SGTEXT, SG_EXIT, 0, 2,8, 35,1, dlgfilenames[2] },
563: { SGTEXT, SG_EXIT, 0, 2,9, 35,1, dlgfilenames[3] },
564: { SGTEXT, SG_EXIT, 0, 2,10, 35,1, dlgfilenames[4] },
565: { SGTEXT, SG_EXIT, 0, 2,11, 35,1, dlgfilenames[5] },
566: { SGTEXT, SG_EXIT, 0, 2,12, 35,1, dlgfilenames[6] },
567: { SGTEXT, SG_EXIT, 0, 2,13, 35,1, dlgfilenames[7] },
568: { SGTEXT, SG_EXIT, 0, 2,14, 35,1, dlgfilenames[8] },
569: { SGTEXT, SG_EXIT, 0, 2,15, 35,1, dlgfilenames[9] },
570: { SGTEXT, SG_EXIT, 0, 2,16, 35,1, dlgfilenames[10] },
571: { SGTEXT, SG_EXIT, 0, 2,17, 35,1, dlgfilenames[11] },
572: { SGTEXT, SG_EXIT, 0, 2,18, 35,1, dlgfilenames[12] },
573: { SGTEXT, SG_EXIT, 0, 2,19, 35,1, dlgfilenames[13] },
574: { SGTEXT, SG_EXIT, 0, 2,20, 35,1, dlgfilenames[14] },
575: { SGTEXT, SG_EXIT, 0, 2,21, 35,1, dlgfilenames[15] },
576: { SGBUTTON, SG_TOUCHEXIT, 0, 38,6, 1,1, "\x01" }, /* Arrow up */
577: { SGBUTTON, SG_TOUCHEXIT, 0, 38,21, 1,1, "\x02" }, /* Arrow down */
578: { SGBUTTON, 0, 0, 10,23, 8,1, "Okay" },
579: { SGBUTTON, 0, 0, 24,23, 8,1, "Cancel" },
580: { -1, 0, 0, 0,0, 0,0, NULL }
581: };
582:
583: zipfilename[0] = 0;
584: SDLGui_CenterDlg(fsdlg);
585:
586: /* Prepare the path and filename variables */
587: File_splitpath(path_and_name, path, fname, NULL);
588: File_ShrinkName(dlgpath, path, 38);
589: File_ShrinkName(dlgfname, fname, 32);
590:
591: /* Save old mouse cursor state and enable cursor anyway */
592: oldcursorstate = SDL_ShowCursor(SDL_QUERY);
593: if( oldcursorstate==SDL_DISABLE )
594: SDL_ShowCursor(SDL_ENABLE);
595:
596: do
597: {
598: if( reloaddir )
599: {
600: if( strlen(path)>=MAX_FILENAME_LENGTH )
601: {
602: fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
603: return FALSE;
604: }
605:
606: /* Free old allocated memory: */
607: if( files!=NULL )
608: {
609: for(i=0; i<entries; i++)
610: {
611: free(files[i]);
612: }
613: free(files);
614: files = NULL;
615: }
616:
617: if( browsingzip )
618: {
619: }
620: else
621: {
622: /* Load directory entries: */
623: entries = scandir(path, &files, 0, alphasort);
624: }
625:
626: if(entries<0)
627: {
628: fprintf(stderr, "SDLGui_FileSelect: Path not found.\n");
629: return FALSE;
630: }
631:
632: reloaddir = FALSE;
633: refreshentries = TRUE;
634: }/* reloaddir */
635:
636:
637: if( refreshentries )
638: {
639: /* Copy entries to dialog: */
640: for(i=0; i<16; i++)
641: {
642: if( i+ypos<entries )
643: {
644: char tempstr[MAX_FILENAME_LENGTH];
645: struct stat filestat;
646: /* Prepare entries: */
647: strcpy(tempstr, " ");
648: strcat(tempstr, files[i+ypos]->d_name);
649: File_ShrinkName(dlgfilenames[i], tempstr, 35);
650: /* Mark folders: */
651: strcpy(tempstr, path);
652: strcat(tempstr, files[i+ypos]->d_name);
653:
654: if( browsingzip )
655: {
656: if( tempstr[strlen(tempstr)-1] == '/' )
657: dlgfilenames[i][0] = SGFOLDER; /* Mark folders */
658: }
659: else
660: {
661: if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
662: dlgfilenames[i][0] = SGFOLDER; /* Mark folders */
663: if( File_FileNameIsZIP(tempstr) && browsingzip == FALSE)
664: dlgfilenames[i][0] = SGFOLDER; /* Mark .ZIP archives as folders */
665: }
666: }
667: else
668: dlgfilenames[i][0] = 0; /* Clear entry */
669: }
670: refreshentries = FALSE;
671: }/* refreshentries */
672:
673: /* Show dialog: */
674: retbut = SDLGui_DoDialog(fsdlg);
675:
676: /* Has the user clicked on a file or folder? */
677: if( retbut>=SGFSDLG_ENTRY1 && retbut<=SGFSDLG_ENTRY16 && retbut-SGFSDLG_ENTRY1+ypos<entries)
678: {
679: char tempstr[MAX_FILENAME_LENGTH];
680: struct stat filestat;
681:
682: if( browsingzip == TRUE )
683: {
684: strcpy(tempstr, zipdir);
685: strcat(tempstr, files[retbut-SGFSDLG_ENTRY1+ypos]->d_name);
686: if(tempstr[strlen(tempstr)-1] == '/')
687: {
688: /* handle the ../ directory */
689: if(strcmp(files[retbut-SGFSDLG_ENTRY1+ypos]->d_name, "../") == 0)
690: {
691: /* close the zip file */
692: if( strcmp(tempstr, "../") == 0 )
693: {
694: }
695: else
696: {
697: i=strlen(tempstr)-1; n=0;
698: while(i > 0 && n < 3) if( tempstr[i--] == '/' )n++;
699: if(tempstr[i+1] == '/') tempstr[i+2] = '\0';
700: else tempstr[0] = '\0';
701:
702: strcpy(zipdir, tempstr);
703: File_ShrinkName(dlgpath, zipdir, 38);
704: }
705: }
706: else /* not the "../" directory */
707: {
708: strcpy(zipdir, tempstr);
709: File_ShrinkName(dlgpath, zipdir, 38);
710: }
711: reloaddir = TRUE;
712: /* Copy the path name to the dialog */
713: selection = -1; /* Remove old selection */
714: zipfilename[0] = '\0';
715: dlgfname[0] = 0;
716: ypos = 0;
717:
718: } else {
719: /* Select a file in the zip */
720: selection = retbut-SGFSDLG_ENTRY1+ypos;
721: strcpy(zipfilename, files[selection]->d_name);
722: File_ShrinkName(dlgfname, zipfilename, 32);
723: }
724:
725: } /* if browsingzip */
726: else
727: {
728: strcpy(tempstr, path);
729: strcat(tempstr, files[retbut-SGFSDLG_ENTRY1+ypos]->d_name);
730: if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
731: {
732: /* Set the new directory */
733: strcpy(path, tempstr);
734: if( strlen(path)>=3 )
735: {
736: if(path[strlen(path)-2]=='/' && path[strlen(path)-1]=='.')
737: path[strlen(path)-2] = 0; /* Strip a single dot at the end of the path name */
738: if(path[strlen(path)-3]=='/' && path[strlen(path)-2]=='.' && path[strlen(path)-1]=='.')
739: {
740: /* Handle the ".." folder */
741: char *ptr;
742: if( strlen(path)==3 )
743: path[1] = 0;
744: else
745: {
746: path[strlen(path)-3] = 0;
747: ptr = strrchr(path, '/');
748: if(ptr) *(ptr+1) = 0;
749: }
750: }
751: }
752: File_AddSlashToEndFileName(path);
753: reloaddir = TRUE;
754: /* Copy the path name to the dialog */
755: File_ShrinkName(dlgpath, path, 38);
756: selection = -1; /* Remove old selection */
757: dlgfname[0] = 0;
758: ypos = 0;
759: }
760: else if ( File_FileNameIsZIP(tempstr) && zip_path != NULL )
761: {
762:
763: } else {
764: /* Select a file */
765: selection = retbut-SGFSDLG_ENTRY1+ypos;
766: strcpy(fname, files[selection]->d_name);
767: File_ShrinkName(dlgfname, fname, 32);
768: }
769:
770: } /* not browsingzip */
771:
772: }
773: else /* Has the user clicked on another button? */
774: {
775: switch(retbut)
776: {
777: case SGFSDLG_UPDIR: /* Change path to parent directory */
778:
779: if( browsingzip )
780: {
781: /* close the zip file */
782: if( strcmp(zipdir, "") == 0 )
783: {
784: reloaddir = refreshentries = TRUE;
785: /* Copy the path name to the dialog */
786: File_ShrinkName(dlgpath, path, 38);
787: browsingzip = FALSE;
788: reloaddir = TRUE;
789: selection = -1; /* Remove old selection */
790: fname[0] = 0;
791: dlgfname[0] = 0;
792: ypos = 0;
793: }
794: else
795: {
796: i=strlen(zipdir)-1; n=0;
797: while(i > 0 && n < 2) if( zipdir[i--] == '/' )n++;
798: if(zipdir[i+1] == '/') zipdir[i+2] = '\0';
799: else zipdir[0] = '\0';
800:
801: File_ShrinkName(dlgpath, zipdir, 38);
802: reloaddir = TRUE;
803: selection = -1; /* Remove old selection */
804: zipfilename[0] = '\0';
805: dlgfname[0] = 0;
806: ypos = 0;
807: }
808: } /* not a zip file: */
809: else if( strlen(path)>2 )
810: {
811: char *ptr;
812: File_CleanFileName(path);
813: ptr = strrchr(path, '/');
814: if(ptr) *(ptr+1) = 0;
815: File_AddSlashToEndFileName(path);
816: reloaddir = TRUE;
817: File_ShrinkName(dlgpath, path, 38); /* Copy the path name to the dialog */
818: selection = -1; /* Remove old selection */
819: fname[0] = 0;
820: dlgfname[0] = 0;
821: ypos = 0;
822: }
823: break;
824: case SGFSDLG_ROOTDIR: /* Change to root directory */
825:
826: strcpy(path, "/");
827: reloaddir = TRUE;
828: strcpy(dlgpath, path);
829: selection = -1; /* Remove old selection */
830: fname[0] = 0;
831: dlgfname[0] = 0;
832: ypos = 0;
833: break;
834: case SGFSDLG_UP: /* Scroll up */
835: if( ypos>0 )
836: {
837: --ypos;
838: refreshentries = TRUE;
839: }
840: SDL_Delay(20);
841: break;
842: case SGFSDLG_DOWN: /* Scroll down */
843: if( ypos+17<=entries )
844: {
845: ++ypos;
846: refreshentries = TRUE;
847: }
848: SDL_Delay(20);
849: break;
850: } /* switch */
851: } /* other button code */
852:
853:
854: } /* do */
855:
856:
857: while(retbut!=SGFSDLG_OKAY && retbut!=SGFSDLG_CANCEL && !bQuitProgram);
858:
859: if( oldcursorstate==SDL_DISABLE )
860: SDL_ShowCursor(SDL_DISABLE);
861:
862: File_makepath(path_and_name, path, fname, NULL);
863:
864: /* Free old allocated memory: */
865: if( files!=NULL )
866: {
867: for(i=0; i<entries; i++)
868: {
869: free(files[i]);
870: }
871: free(files);
872: files = NULL;
873: }
874:
875: return( retbut==SGFSDLG_OKAY );
876: }
877:
878:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.