|
|
hatari 0.40
/*
Hatari - sdlgui.c
This file is distributed under the GNU Public License, version 2 or at
your option any later version. Read the file gpl.txt for details.
A tiny graphical user interface for Hatari.
*/
static char rcsid[] = "Hatari $Id: sdlgui.c,v 1.1.1.3 2019/04/01 07:10:52 root Exp $";
#include <SDL.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "main.h"
#include "memAlloc.h"
#include "screen.h"
#include "sdlgui.h"
#include "file.h"
#include "zip.h"
#define SGRADIOBUTTON_NORMAL 12
#define SGRADIOBUTTON_SELECTED 13
#define SGCHECKBOX_NORMAL 14
#define SGCHECKBOX_SELECTED 15
#define SGARROWUP 1
#define SGARROWDOWN 2
#define SGFOLDER 5
static SDL_Surface *stdfontgfx = NULL; /* The 'standard' font graphics */
static SDL_Surface *fontgfx = NULL; /* The actual font graphics */
static int fontwidth, fontheight; /* Height and width of the actual font */
/*-----------------------------------------------------------------------*/
/*
Initialize the GUI.
*/
int SDLGui_Init()
{
char fontname[256];
sprintf(fontname, "%s/font8.bmp", DATADIR);
/* Load the font graphics: */
stdfontgfx = SDL_LoadBMP(fontname);
if( stdfontgfx==NULL )
{
fprintf(stderr, "Error: Can't load image %s: %s\n", fontname, SDL_GetError() );
return -1;
}
return 0;
}
/*-----------------------------------------------------------------------*/
/*
Uninitialize the GUI.
*/
int SDLGui_UnInit()
{
if(stdfontgfx)
{
SDL_FreeSurface(stdfontgfx);
stdfontgfx = NULL;
}
if(fontgfx)
{
SDL_FreeSurface(fontgfx);
fontgfx = NULL;
}
return 0;
}
/*-----------------------------------------------------------------------*/
/*
Prepare the font to suit the actual resolution.
*/
int SDLGui_PrepareFont()
{
/* FIXME: Freeing the old font gfx does sometimes crash with a SEGFAULT
if(fontgfx)
{
SDL_FreeSurface(fontgfx);
fontgfx = NULL;
}
*/
if( stdfontgfx==NULL )
{
fprintf(stderr, "Error: The font has not been loaded!\n");
return -1;
}
/* Convert the font graphics to the actual screen format */
fontgfx = SDL_DisplayFormat(stdfontgfx);
if( fontgfx==NULL )
{
fprintf(stderr, "Could not convert font:\n %s\n", SDL_GetError() );
return -1;
}
/* Set transparent pixel */
SDL_SetColorKey(fontgfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), SDL_MapRGB(fontgfx->format,255,255,255));
/* Get the font width and height: */
fontwidth = fontgfx->w/16;
fontheight = fontgfx->h/16;
return 0;
}
/*-----------------------------------------------------------------------*/
/*
Center a dialog so that it appears in the middle of the screen.
Note: We only store the coordinates in the root box of the dialog,
all other objects in the dialog are positioned relatively to this one.
*/
void SDLGui_CenterDlg(SGOBJ *dlg)
{
dlg[0].x = (sdlscrn->w/fontwidth-dlg[0].w)/2;
dlg[0].y = (sdlscrn->h/fontheight-dlg[0].h)/2;
}
/*-----------------------------------------------------------------------*/
/*
Draw a text string.
*/
void SDLGui_Text(int x, int y, const char *txt)
{
int i;
char c;
SDL_Rect sr, dr;
for(i=0; txt[i]!=0; i++)
{
c = txt[i];
sr.x=fontwidth*(c%16); sr.y=fontheight*(c/16);
sr.w=fontwidth; sr.h=fontheight;
dr.x=x+i*fontwidth; dr.y=y;
dr.w=fontwidth; dr.h=fontheight;
SDL_BlitSurface(fontgfx, &sr, sdlscrn, &dr);
}
}
/*-----------------------------------------------------------------------*/
/*
Draw a dialog text object.
*/
void SDLGui_DrawText(SGOBJ *tdlg, int objnum)
{
int x, y;
x = (tdlg[0].x+tdlg[objnum].x)*fontwidth;
y = (tdlg[0].y+tdlg[objnum].y)*fontheight;
SDLGui_Text(x, y, tdlg[objnum].txt);
}
/*-----------------------------------------------------------------------*/
/*
Draw a dialog box object.
*/
void SDLGui_DrawBox(SGOBJ *bdlg, int objnum)
{
SDL_Rect rect;
int x, y, w, h;
Uint32 grey = SDL_MapRGB(sdlscrn->format,192,192,192);
Uint32 upleftc, downrightc;
x = bdlg[objnum].x*fontwidth;
y = bdlg[objnum].y*fontheight;
if(objnum>0) /* Since the root object is a box, too, */
{ /* we have to look for it now here and only */
x += bdlg[0].x*fontwidth; /* add its absolute coordinates if we need to */
y += bdlg[0].y*fontheight;
}
w = bdlg[objnum].w*fontwidth;
h = bdlg[objnum].h*fontheight;
if( bdlg[objnum].state&SG_SELECTED )
{
upleftc = SDL_MapRGB(sdlscrn->format,128,128,128);
downrightc = SDL_MapRGB(sdlscrn->format,255,255,255);
}
else
{
upleftc = SDL_MapRGB(sdlscrn->format,255,255,255);
downrightc = SDL_MapRGB(sdlscrn->format,128,128,128);
}
rect.x = x; rect.y = y;
rect.w = w; rect.h = h;
SDL_FillRect(sdlscrn, &rect, grey);
rect.x = x; rect.y = y-1;
rect.w = w; rect.h = 1;
SDL_FillRect(sdlscrn, &rect, upleftc);
rect.x = x-1; rect.y = y;
rect.w = 1; rect.h = h;
SDL_FillRect(sdlscrn, &rect, upleftc);
rect.x = x; rect.y = y+h;
rect.w = w; rect.h = 1;
SDL_FillRect(sdlscrn, &rect, downrightc);
rect.x = x+w; rect.y = y;
rect.w = 1; rect.h = h;
SDL_FillRect(sdlscrn, &rect, downrightc);
}
/*-----------------------------------------------------------------------*/
/*
Draw a normal button.
*/
void SDLGui_DrawButton(SGOBJ *bdlg, int objnum)
{
int x,y;
SDLGui_DrawBox(bdlg, objnum);
x = (bdlg[0].x+bdlg[objnum].x+(bdlg[objnum].w-strlen(bdlg[objnum].txt))/2)*fontwidth;
y = (bdlg[0].y+bdlg[objnum].y+(bdlg[objnum].h-1)/2)*fontheight;
if( bdlg[objnum].state&SG_SELECTED )
{
x+=1;
y+=1;
}
SDLGui_Text(x, y, bdlg[objnum].txt);
}
/*-----------------------------------------------------------------------*/
/*
Draw a dialog radio button object.
*/
void SDLGui_DrawRadioButton(SGOBJ *rdlg, int objnum)
{
char str[80];
int x, y;
x = (rdlg[0].x+rdlg[objnum].x)*fontwidth;
y = (rdlg[0].y+rdlg[objnum].y)*fontheight;
if( rdlg[objnum].state&SG_SELECTED )
str[0]=SGRADIOBUTTON_SELECTED;
else
str[0]=SGRADIOBUTTON_NORMAL;
str[1]=' ';
strcpy(&str[2], rdlg[objnum].txt);
SDLGui_Text(x, y, str);
}
/*-----------------------------------------------------------------------*/
/*
Draw a dialog check box object.
*/
void SDLGui_DrawCheckBox(SGOBJ *cdlg, int objnum)
{
char str[80];
int x, y;
x = (cdlg[0].x+cdlg[objnum].x)*fontwidth;
y = (cdlg[0].y+cdlg[objnum].y)*fontheight;
if( cdlg[objnum].state&SG_SELECTED )
str[0]=SGCHECKBOX_SELECTED;
else
str[0]=SGCHECKBOX_NORMAL;
str[1]=' ';
strcpy(&str[2], cdlg[objnum].txt);
SDLGui_Text(x, y, str);
}
/*-----------------------------------------------------------------------*/
/*
Draw a dialog popup button object.
*/
void SDLGui_DrawPopupButton(SGOBJ *pdlg, int objnum)
{
int x, y, w, h;
const char *downstr = "\x02";
SDLGui_DrawBox(pdlg, objnum);
x = (pdlg[0].x+pdlg[objnum].x)*fontwidth;
y = (pdlg[0].y+pdlg[objnum].y)*fontheight;
w = pdlg[objnum].w*fontwidth;
h = pdlg[objnum].h*fontheight;
SDLGui_Text(x, y, pdlg[objnum].txt);
SDLGui_Text(x+w-fontwidth, y, downstr);
}
/*-----------------------------------------------------------------------*/
/*
Draw a whole dialog.
*/
void SDLGui_DrawDialog(SGOBJ *dlg)
{
int i;
for(i=0; dlg[i].type!=-1; i++ )
{
switch( dlg[i].type )
{
case SGBOX:
SDLGui_DrawBox(dlg, i);
break;
case SGTEXT:
SDLGui_DrawText(dlg, i);
break;
case SGBUTTON:
SDLGui_DrawButton(dlg, i);
break;
case SGRADIOBUT:
SDLGui_DrawRadioButton(dlg, i);
break;
case SGCHECKBOX:
SDLGui_DrawCheckBox(dlg, i);
break;
case SGPOPUP:
SDLGui_DrawPopupButton(dlg, i);
break;
}
}
SDL_UpdateRect(sdlscrn, 0,0,0,0);
}
/*-----------------------------------------------------------------------*/
/*
Search an object at a certain position.
*/
int SDLGui_FindObj(SGOBJ *dlg, int fx, int fy)
{
int len, i;
int ob = -1;
int xpos, ypos;
len = 0;
while( dlg[len].type!=-1) len++;
xpos = fx/fontwidth;
ypos = fy/fontheight;
/* Now search for the object: */
for(i=len; i>0; i--)
{
if(xpos>=dlg[0].x+dlg[i].x && ypos>=dlg[0].y+dlg[i].y
&& xpos<dlg[0].x+dlg[i].x+dlg[i].w && ypos<dlg[0].y+dlg[i].y+dlg[i].h)
{
ob = i;
break;
}
}
return ob;
}
/*-----------------------------------------------------------------------*/
/*
Show and process a dialog. Returns the button number that has been
pressed or -1 if something went wrong.
*/
int SDLGui_DoDialog(SGOBJ *dlg)
{
int obj=0;
int oldbutton=0;
int retbutton=0;
int i, j, b;
SDL_Event evnt;
SDL_Rect rct;
Uint32 grey;
grey = SDL_MapRGB(sdlscrn->format,192,192,192);
SDLGui_DrawDialog(dlg);
/* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
SDL_PumpEvents();
b = SDL_GetMouseState(&i, &j);
obj = SDLGui_FindObj(dlg, i, j);
if(obj>0 && (dlg[obj].flags&SG_TOUCHEXIT) )
{
oldbutton = obj;
if( b&SDL_BUTTON(1) )
{
dlg[obj].state |= SG_SELECTED;
return obj;
}
}
/* The main loop */
do
{
if( SDL_WaitEvent(&evnt)==1 ) /* Wait for events */
switch(evnt.type)
{
case SDL_KEYDOWN:
break;
case SDL_QUIT:
bQuitProgram = TRUE;
break;
case SDL_MOUSEBUTTONDOWN:
obj = SDLGui_FindObj(dlg, evnt.button.x, evnt.button.y);
if(obj>0)
{
if(dlg[obj].type==SGBUTTON)
{
dlg[obj].state |= SG_SELECTED;
SDLGui_DrawButton(dlg, obj);
SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
oldbutton=obj;
}
if( dlg[obj].flags&SG_TOUCHEXIT )
{
dlg[obj].state |= SG_SELECTED;
retbutton = obj;
}
}
break;
case SDL_MOUSEBUTTONUP:
obj = SDLGui_FindObj(dlg, evnt.button.x, evnt.button.y);
if(obj>0)
{
switch(dlg[obj].type)
{
case SGBUTTON:
if(oldbutton==obj)
retbutton=obj;
break;
case SGRADIOBUT:
for(i=obj-1; i>0 && dlg[i].type==SGRADIOBUT; i--)
{
dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
rct.y = (dlg[0].y+dlg[i].y)*fontheight;
rct.w = fontwidth; rct.h = fontheight;
SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
SDLGui_DrawRadioButton(dlg, i);
SDL_UpdateRects(sdlscrn, 1, &rct);
}
for(i=obj+1; dlg[i].type==SGRADIOBUT; i++)
{
dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
rct.y = (dlg[0].y+dlg[i].y)*fontheight;
rct.w = fontwidth; rct.h = fontheight;
SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
SDLGui_DrawRadioButton(dlg, i);
SDL_UpdateRects(sdlscrn, 1, &rct);
}
dlg[obj].state |= SG_SELECTED; /* Select this radio button */
rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
rct.w = fontwidth; rct.h = fontheight;
SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
SDLGui_DrawRadioButton(dlg, obj);
SDL_UpdateRects(sdlscrn, 1, &rct);
break;
case SGCHECKBOX:
dlg[obj].state ^= SG_SELECTED;
rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
rct.w = fontwidth; rct.h = fontheight;
SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
SDLGui_DrawCheckBox(dlg, obj);
SDL_UpdateRects(sdlscrn, 1, &rct);
break;
case SGPOPUP:
dlg[obj].state |= SG_SELECTED;
SDLGui_DrawPopupButton(dlg, obj);
SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
retbutton=obj;
break;
}
}
if(oldbutton>0)
{
dlg[oldbutton].state &= ~SG_SELECTED;
SDLGui_DrawButton(dlg, oldbutton);
SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[oldbutton].x)*fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*fontheight-2,
dlg[oldbutton].w*fontwidth+4, dlg[oldbutton].h*fontheight+4);
oldbutton = 0;
}
if( dlg[obj].flags&SG_EXIT )
{
retbutton = obj;
}
break;
}
}
while(retbutton==0 && !bQuitProgram);
if(bQuitProgram)
retbutton=-1;
return retbutton;
}
/*-----------------------------------------------------------------------*/
/*
Show and process a file select dialog.
Returns TRUE if the use selected "okay", FALSE if "cancel".
input: zip_path = pointer to buffer to contain file path within a selected
zip file, or NULL if browsing zip files is disallowed.
*/
#define SGFSDLG_UPDIR 6
#define SGFSDLG_ROOTDIR 7
#define SGFSDLG_ENTRY1 10
#define SGFSDLG_ENTRY16 25
#define SGFSDLG_UP 26
#define SGFSDLG_DOWN 27
#define SGFSDLG_OKAY 28
#define SGFSDLG_CANCEL 29
int SDLGui_FileSelect(char *path_and_name, char *zip_path)
{
int i,n;
int entries = 0; /* How many files are in the actual directory? */
int ypos = 0;
char dlgfilenames[16][36];
struct dirent **files = NULL;
char path[MAX_FILENAME_LENGTH], fname[128]; /* The actual file and path names */
char dlgpath[39], dlgfname[33]; /* File and path name in the dialog */
BOOL reloaddir = TRUE; /* Do we have to reload the directory file list? */
BOOL refreshentries = TRUE; /* Do we have to update the file names in the dialog? */
int retbut;
int oldcursorstate;
int selection = -1; /* The actual selection, -1 if none selected */
char zipfilename[MAX_FILENAME_LENGTH]; /* Filename in zip file */
char zipdir[MAX_FILENAME_LENGTH];
BOOL browsingzip = FALSE; /* Are we browsing an archive? */
zip_dir *zipfiles = NULL;
SGOBJ fsdlg[] =
{
{ SGBOX, 0, 0, 0,0, 40,25, NULL },
{ SGTEXT, 0, 0, 13,1, 13,1, "Choose a file" },
{ SGTEXT, 0, 0, 1,2, 7,1, "Folder:" },
{ SGTEXT, 0, 0, 1,3, 38,1, dlgpath },
{ SGTEXT, 0, 0, 1,4, 6,1, "File:" },
{ SGTEXT, 0, 0, 7,4, 31,1, dlgfname },
{ SGBUTTON, 0, 0, 31,1, 4,1, ".." },
{ SGBUTTON, 0, 0, 36,1, 3,1, "/" },
{ SGBOX, 0, 0, 1,6, 38,16, NULL },
{ SGBOX, 0, 0, 38,7, 1,14, NULL },
{ SGTEXT, SG_EXIT, 0, 2,6, 35,1, dlgfilenames[0] },
{ SGTEXT, SG_EXIT, 0, 2,7, 35,1, dlgfilenames[1] },
{ SGTEXT, SG_EXIT, 0, 2,8, 35,1, dlgfilenames[2] },
{ SGTEXT, SG_EXIT, 0, 2,9, 35,1, dlgfilenames[3] },
{ SGTEXT, SG_EXIT, 0, 2,10, 35,1, dlgfilenames[4] },
{ SGTEXT, SG_EXIT, 0, 2,11, 35,1, dlgfilenames[5] },
{ SGTEXT, SG_EXIT, 0, 2,12, 35,1, dlgfilenames[6] },
{ SGTEXT, SG_EXIT, 0, 2,13, 35,1, dlgfilenames[7] },
{ SGTEXT, SG_EXIT, 0, 2,14, 35,1, dlgfilenames[8] },
{ SGTEXT, SG_EXIT, 0, 2,15, 35,1, dlgfilenames[9] },
{ SGTEXT, SG_EXIT, 0, 2,16, 35,1, dlgfilenames[10] },
{ SGTEXT, SG_EXIT, 0, 2,17, 35,1, dlgfilenames[11] },
{ SGTEXT, SG_EXIT, 0, 2,18, 35,1, dlgfilenames[12] },
{ SGTEXT, SG_EXIT, 0, 2,19, 35,1, dlgfilenames[13] },
{ SGTEXT, SG_EXIT, 0, 2,20, 35,1, dlgfilenames[14] },
{ SGTEXT, SG_EXIT, 0, 2,21, 35,1, dlgfilenames[15] },
{ SGBUTTON, SG_TOUCHEXIT, 0, 38,6, 1,1, "\x01" }, /* Arrow up */
{ SGBUTTON, SG_TOUCHEXIT, 0, 38,21, 1,1, "\x02" }, /* Arrow down */
{ SGBUTTON, 0, 0, 10,23, 8,1, "Okay" },
{ SGBUTTON, 0, 0, 24,23, 8,1, "Cancel" },
{ -1, 0, 0, 0,0, 0,0, NULL }
};
zipfilename[0] = 0;
SDLGui_CenterDlg(fsdlg);
/* Prepare the path and filename variables */
File_splitpath(path_and_name, path, fname, NULL);
File_ShrinkName(dlgpath, path, 38);
File_ShrinkName(dlgfname, fname, 32);
/* Save old mouse cursor state and enable cursor anyway */
oldcursorstate = SDL_ShowCursor(SDL_QUERY);
if( oldcursorstate==SDL_DISABLE )
SDL_ShowCursor(SDL_ENABLE);
do
{
if( reloaddir )
{
if( strlen(path)>=MAX_FILENAME_LENGTH )
{
fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
return FALSE;
}
/* Free old allocated memory: */
if( files!=NULL )
{
for(i=0; i<entries; i++)
{
free(files[i]);
}
free(files);
files = NULL;
}
if( browsingzip )
{
files = ZIP_GetFilesDir(zipfiles, zipdir, &entries);
}
else
{
/* Load directory entries: */
entries = scandir(path, &files, 0, alphasort);
}
if(entries<0)
{
fprintf(stderr, "SDLGui_FileSelect: Path not found.\n");
return FALSE;
}
reloaddir = FALSE;
refreshentries = TRUE;
}/* reloaddir */
if( refreshentries )
{
/* Copy entries to dialog: */
for(i=0; i<16; i++)
{
if( i+ypos<entries )
{
char tempstr[MAX_FILENAME_LENGTH];
struct stat filestat;
/* Prepare entries: */
strcpy(tempstr, " ");
strcat(tempstr, files[i+ypos]->d_name);
File_ShrinkName(dlgfilenames[i], tempstr, 35);
/* Mark folders: */
strcpy(tempstr, path);
strcat(tempstr, files[i+ypos]->d_name);
if( browsingzip )
{
if( tempstr[strlen(tempstr)-1] == '/' )
dlgfilenames[i][0] = SGFOLDER; /* Mark folders */
}
else
{
if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
dlgfilenames[i][0] = SGFOLDER; /* Mark folders */
if( File_FileNameIsZIP(tempstr) && browsingzip == FALSE)
dlgfilenames[i][0] = SGFOLDER; /* Mark .ZIP archives as folders */
}
}
else
dlgfilenames[i][0] = 0; /* Clear entry */
}
refreshentries = FALSE;
}/* refreshentries */
/* Show dialog: */
retbut = SDLGui_DoDialog(fsdlg);
/* Has the user clicked on a file or folder? */
if( retbut>=SGFSDLG_ENTRY1 && retbut<=SGFSDLG_ENTRY16 && retbut-SGFSDLG_ENTRY1+ypos<entries)
{
char tempstr[MAX_FILENAME_LENGTH];
struct stat filestat;
if( browsingzip == TRUE )
{
strcpy(tempstr, zipdir);
strcat(tempstr, files[retbut-SGFSDLG_ENTRY1+ypos]->d_name);
if(tempstr[strlen(tempstr)-1] == '/')
{
/* handle the ../ directory */
if(strcmp(files[retbut-SGFSDLG_ENTRY1+ypos]->d_name, "../") == 0)
{
/* close the zip file */
if( strcmp(tempstr, "../") == 0 )
{
reloaddir = refreshentries = TRUE;
/* free zip file entries */
while(zipfiles->nfiles > 0)
{
Memory_Free(zipfiles->names[zipfiles->nfiles-1]);
zipfiles->nfiles--;
}
Memory_Free(zipfiles);
/* Copy the path name to the dialog */
File_ShrinkName(dlgpath, path, 38);
browsingzip = FALSE;
}
else
{
i=strlen(tempstr)-1; n=0;
while(i > 0 && n < 3) if( tempstr[i--] == '/' )n++;
if(tempstr[i+1] == '/') tempstr[i+2] = '\0';
else tempstr[0] = '\0';
strcpy(zipdir, tempstr);
File_ShrinkName(dlgpath, zipdir, 38);
}
}
else /* not the "../" directory */
{
strcpy(zipdir, tempstr);
File_ShrinkName(dlgpath, zipdir, 38);
}
reloaddir = TRUE;
/* Copy the path name to the dialog */
selection = -1; /* Remove old selection */
zipfilename[0] = '\0';
dlgfname[0] = 0;
ypos = 0;
} else {
/* Select a file in the zip */
selection = retbut-SGFSDLG_ENTRY1+ypos;
strcpy(zipfilename, files[selection]->d_name);
File_ShrinkName(dlgfname, zipfilename, 32);
}
} /* if browsingzip */
else
{
strcpy(tempstr, path);
strcat(tempstr, files[retbut-SGFSDLG_ENTRY1+ypos]->d_name);
if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
{
/* Set the new directory */
strcpy(path, tempstr);
if( strlen(path)>=3 )
{
if(path[strlen(path)-2]=='/' && path[strlen(path)-1]=='.')
path[strlen(path)-2] = 0; /* Strip a single dot at the end of the path name */
if(path[strlen(path)-3]=='/' && path[strlen(path)-2]=='.' && path[strlen(path)-1]=='.')
{
/* Handle the ".." folder */
char *ptr;
if( strlen(path)==3 )
path[1] = 0;
else
{
path[strlen(path)-3] = 0;
ptr = strrchr(path, '/');
if(ptr) *(ptr+1) = 0;
}
}
}
File_AddSlashToEndFileName(path);
reloaddir = TRUE;
/* Copy the path name to the dialog */
File_ShrinkName(dlgpath, path, 38);
selection = -1; /* Remove old selection */
dlgfname[0] = 0;
ypos = 0;
}
else if ( File_FileNameIsZIP(tempstr) && zip_path != NULL )
{
/* open a zip file */
zipfiles = ZIP_GetFiles(tempstr);
if( zipfiles != NULL && browsingzip == FALSE )
{
selection = retbut-SGFSDLG_ENTRY1+ypos;
strcpy(fname, files[selection]->d_name);
File_ShrinkName(dlgfname, fname, 32);
browsingzip=TRUE;
strcpy(zipdir, "");
File_ShrinkName(dlgpath, zipdir, 38);
reloaddir = refreshentries = TRUE;
ypos = 0;
}
} else {
/* Select a file */
selection = retbut-SGFSDLG_ENTRY1+ypos;
strcpy(fname, files[selection]->d_name);
File_ShrinkName(dlgfname, fname, 32);
}
} /* not browsingzip */
}
else /* Has the user clicked on another button? */
{
switch(retbut)
{
case SGFSDLG_UPDIR: /* Change path to parent directory */
if( browsingzip )
{
/* close the zip file */
if( strcmp(zipdir, "") == 0 )
{
reloaddir = refreshentries = TRUE;
/* free zip file entries */
while(zipfiles->nfiles > 0)
{
Memory_Free(zipfiles->names[zipfiles->nfiles-1]);
zipfiles->nfiles--;
}
Memory_Free(zipfiles);
/* Copy the path name to the dialog */
File_ShrinkName(dlgpath, path, 38);
browsingzip = FALSE;
reloaddir = TRUE;
selection = -1; /* Remove old selection */
fname[0] = 0;
dlgfname[0] = 0;
ypos = 0;
}
else
{
i=strlen(zipdir)-1; n=0;
while(i > 0 && n < 2) if( zipdir[i--] == '/' )n++;
if(zipdir[i+1] == '/') zipdir[i+2] = '\0';
else zipdir[0] = '\0';
File_ShrinkName(dlgpath, zipdir, 38);
reloaddir = TRUE;
selection = -1; /* Remove old selection */
zipfilename[0] = '\0';
dlgfname[0] = 0;
ypos = 0;
}
} /* not a zip file: */
else if( strlen(path)>2 )
{
char *ptr;
File_CleanFileName(path);
ptr = strrchr(path, '/');
if(ptr) *(ptr+1) = 0;
File_AddSlashToEndFileName(path);
reloaddir = TRUE;
File_ShrinkName(dlgpath, path, 38); /* Copy the path name to the dialog */
selection = -1; /* Remove old selection */
fname[0] = 0;
dlgfname[0] = 0;
ypos = 0;
}
break;
case SGFSDLG_ROOTDIR: /* Change to root directory */
if( browsingzip )
{
/* free zip file entries */
while(zipfiles->nfiles > 0)
{
Memory_Free(zipfiles->names[zipfiles->nfiles-1]);
zipfiles->nfiles--;
}
Memory_Free(zipfiles);
browsingzip = FALSE;
}
strcpy(path, "/");
reloaddir = TRUE;
strcpy(dlgpath, path);
selection = -1; /* Remove old selection */
fname[0] = 0;
dlgfname[0] = 0;
ypos = 0;
break;
case SGFSDLG_UP: /* Scroll up */
if( ypos>0 )
{
--ypos;
refreshentries = TRUE;
}
SDL_Delay(20);
break;
case SGFSDLG_DOWN: /* Scroll down */
if( ypos+17<=entries )
{
++ypos;
refreshentries = TRUE;
}
SDL_Delay(20);
break;
} /* switch */
} /* other button code */
} /* do */
while(retbut!=SGFSDLG_OKAY && retbut!=SGFSDLG_CANCEL && !bQuitProgram);
if( oldcursorstate==SDL_DISABLE )
SDL_ShowCursor(SDL_DISABLE);
File_makepath(path_and_name, path, fname, NULL);
/* Free old allocated memory: */
if( files!=NULL )
{
for(i=0; i<entries; i++)
{
free(files[i]);
}
free(files);
files = NULL;
}
if( browsingzip )
{
/* free zip file entries */
while(zipfiles->nfiles > 0)
{
Memory_Free(zipfiles->names[zipfiles->nfiles-1]);
zipfiles->nfiles--;
}
Memory_Free(zipfiles);
}
if( zip_path != NULL )
{
if( browsingzip )
{
strcpy(zip_path, zipdir);
strcat(zip_path, zipfilename);
} else zip_path[0] = '\0';
}
return( retbut==SGFSDLG_OKAY );
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.