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