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