|
|
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.