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