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