linapple-pie/src/DiskChoose.cpp

460 lines
14 KiB
C++

/*
////////////////////////////////////////////////////////////////////////////
//////////// Choose disk image for given slot number? ////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//// Adapted for linapple - apple][ emulator for Linux by beom beotiger Nov 2007 /////
///////////////////////////////////////////////////////////////////////////////////////
// Original source from one of Brain Games (http://www.braingames.getput.com)
// game Super Transball 2.(http://www.braingames.getput.com/stransball2/default.asp)
//
// Brain Games crew creates brilliant retro-remakes! Please visit their site to find out more.
//
*/
#ifdef _WIN32
#include "windows.h"
#else
#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "ctype.h"
#endif
#include "stdafx.h"
#include "list.h"
#include "DiskChoose.h"
//#include "ctype.h"
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//#include "SDL/SDL.h"
//#include "SDL_mixer.h"
//#include "SDL_image.h"
/*
#include "auxiliar.h"
#include "tiles.h"
#include "maps.h"
#include "transball.h"
#include "encoder.h"
*/
// how many file names we are able to see at once!
#define FILES_IN_SCREEN 21
// delay after key pressed (in milliseconds??)
#define KEY_DELAY 25
/////////////////////////////////////////////////////////////////////
/* FONT prev decls */
//bool fonts_initialization(void);
//void font_print(int x,int y,char *text,SDL_Surface *surface);
//void font_print_centered(int x,int y, char *text, SDL_Surface *surface);
/////////////////////////////////////////////////////////////////////
/* AUX funcs prev decls */
//void rectangle(SDL_Surface *surface, int x, int y, int w, int h, Uint32 pixel);
//void surface_fader(SDL_Surface *surface,float r_factor,float g_factor,float b_factor,float a_factor,SDL_Rect *r);
////////////////////////////////////////////////////////////////////////////////////////
#ifndef _WIN32
int getstat(char *catalog, char *fname, int * size)
{
// gets file status and returns: 0 - special or error, 1 - file is a directory, 2 - file is a normal file
// In: catalog - working directory, fname - file name
struct stat info;
char tempname[MAX_PATH];
snprintf(tempname, MAX_PATH, "%s/%s", catalog, fname); // get full path for the file
if(stat(tempname, &info) == -1) return 0;
if(S_ISDIR(info.st_mode)) return 1; // seems to be directory
if(S_ISREG(info.st_mode)) {
if(size != NULL) *size = (int)(info.st_size / 1024); // get file size in Kbytes?!
return 2; // regular file
}
return 0;
}
#endif
////////////////////////////////////////////////////////////////////////////////////////
bool ChooseAnImage(int sx,int sy, char *incoming_dir, int slot, char **filename, bool *isdir, int *index_file)
{
/* Parameters:
sx, sy - window size,
incoming_dir - in what dir find files,
slot - in what slot should an image go (common: #6 for 5.25' 140Kb floppy disks, and #7 for hard-disks).
slot #5 - for 800Kb floppy disks, but we do not use them in Apple][?
(They are as a rule with .2mg extension)
index_file - from which file we should start cursor (should be static and 0 when changing dir)
Out: filename - chosen file name (or dir name)
isdir - if chosen name is a directory
*/
/* Surface: */
SDL_Surface *my_screen; // for background
if(font_sfc == NULL)
if(!fonts_initialization()) return false; //if we don't have a fonts, we just can do none
List<char> files; // our files
List<char> sizes; // and their sizes (or 'dir' for directories)
int act_file; // current file
int first_file; // from which we output files
printf("Disckchoose! We are here: %s\n",incoming_dir);
// files.Delete();
// sizes.Delete();
#ifndef _WIN32
/* POSIX specific routines of reading directory structure */
DIR *dp;
struct dirent *ep;
dp = opendir (incoming_dir); // open and read incoming directory
char *tmp;
int i,j, B, N; // for cycles, beginning and end of list
// build prev dir
if(strcmp(incoming_dir, "/")) {
tmp = new char[3];
strcpy(tmp, "..");
files.Add(tmp);
tmp = new char[5];
strcpy(tmp, "<UP>");
sizes.Add(tmp); // add sign of directory
B = 1;
}
else B = 0; // for sorting dirs
if (dp != NULL)
{
while (ep = readdir (dp)) // first looking for directories
{
int what = getstat(incoming_dir, ep->d_name, NULL);
if (strlen(ep->d_name) > 0 && /*strcmp(ep->d_name,".")*/// omit "." (cur dir)
ep->d_name[0] != '.'/*strcmp(ep->d_name,"..")*/ && what == 1) // is directory!
{
tmp = new char[strlen(ep->d_name)+1]; // add entity to list
strcpy(tmp, ep->d_name);
files.Add(tmp);
tmp = new char[6];
strcpy(tmp, "<DIR>");
sizes.Add(tmp); // add sign of directory
} /* if */
}
}
#else
/* Windows specific functions of reading directory structure */
/* Find subdirs: */
if(strcmp(incoming_dir, "/")) {
// we are not in upper direcory
tmp = new char[3];
strcpy(tmp, "..");
files.Add(tmp);
tmp = new char[5];
strcpy(tmp, "<UP>");
sizes.Add(tmp); // add sign of directory
B = 1;
}
else B = 0; // for sorting dirs
WIN32_FIND_DATA finfo;
HANDLE h;
h=FindFirstFile(incoming_dir,&finfo);
if (h!=INVALID_HANDLE_VALUE) {
char *tmp;
if(finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0) {
// add this entry if it is directory
tmp=new char[strlen(finfo.cFileName)+1];
strcpy(tmp,finfo.cFileName);
files.Add(tmp);
tmp = new char[6];
strcpy(tmp, "<DIR>");
sizes.Add(tmp); // add sign of directory
}
while(FindNextFile(h,&finfo)==TRUE) {
if(finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0) {
// add this entry if it is directory
tmp=new char[strlen(finfo.cFileName)+1];
strcpy(tmp,finfo.cFileName);
files.Add(tmp);
tmp = new char[6];
strcpy(tmp, "<DIR>");
sizes.Add(tmp); // add sign of directory
}
} /* while */
} /* if */
#endif
// sort directories. Please, don't laugh at my bubble sorting - it the simplest thing I've ever seen --bb
if(files.Length() > 2)
{
N = files.Length() - 1;
// B = 1;`- defined above
for(i = N; i > B; i--)
for(j = B; j < i; j++)
if(strcasecmp(files[j], files[j + 1]) > 0)
{
files.Swap(j,j + 1);
sizes.Swap(j,j + 1);
}
}
B = files.Length(); // start for files
#ifndef _WIN32
/* POSIX specific routines of reading directory structure */
(void) rewinddir (dp); // to the start
// now get all regular files
while (ep = readdir (dp))
{
int fsize;
if (strlen(ep->d_name) > 4 && ep->d_name[0] != '.'
&& (getstat(incoming_dir, ep->d_name, &fsize) == 2)) // is normal file!
{
tmp = new char[strlen(ep->d_name)+1]; // add this entity to list
strcpy(tmp, ep->d_name);
files.Add(tmp);
tmp = new char[10]; // 1400000KB
snprintf(tmp, 9, "%dKB", fsize);
sizes.Add(tmp); // add this size to list
} /* if */
}
(void) closedir (dp);
#else
/* Windows specific functions of reading directory structure */
/* Find files: */
h=FindFirstFile(incoming_dir,&finfo);
if (h!=INVALID_HANDLE_VALUE) {
// char *tmp; - must be defined in previous section, when searching subdirs
if(finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0) {
// add this entry if it is NOT directory!
tmp=new char[strlen(finfo.cFileName)+1];
strcpy(tmp,finfo.cFileName);
files.Add(tmp);
tmp = new char[10]; // 1400000KB
snprintf(tmp, 9, "%dKB",
((finfo.nFileSizeHigh * (MAXDWORD+1)) + finfo.nFileSizeLow));
sizes.Add(tmp); // add this size to list
}
while(FindNextFile(h,&finfo)==TRUE) {
if(finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0) {
// add this entry if it is NOT directory!
tmp=new char[strlen(finfo.cFileName)+1];
strcpy(tmp,finfo.cFileName);
files.Add(tmp);
tmp = new char[10]; // 1400000KB
snprintf(tmp, 9, "%dKB",
((finfo.nFileSizeHigh * (MAXDWORD+1)) + finfo.nFileSizeLow));
sizes.Add(tmp); // add this size to list
}
} /* while */
} /* if */
#endif
// do sorting for files
if(files.Length() > 2 && B < files.Length())
{
N = files.Length() - 1;
// B = 1;
for(i = N; i > B; i--)
for(j = B; j < i; j++)
if(strcasecmp(files[j], files[j + 1]) > 0)
{
files.Swap(j,j + 1);
sizes.Swap(j,j + 1);
}
}
// Count out cursor position and file number output
act_file = *index_file;
if(act_file >= files.Length()) act_file = 0; // cannot be more than files in list
first_file = act_file - (FILES_IN_SCREEN / 2);
if (first_file < 0) first_file = 0; // cannot be negativ...
// Show all directories (first) and files then
// char *tmp;
char *siz;
// int i;
// prepare screen
double facx = double(g_ScreenWidth) / double(SCREEN_WIDTH);
double facy = double(g_ScreenHeight) / double(SCREEN_HEIGHT);
SDL_Surface *tempSurface = NULL;
if(!g_WindowResized) {
if(g_nAppMode == MODE_LOGO) tempSurface = g_hLogoBitmap; // use logobitmap
else tempSurface = g_hDeviceBitmap;
}
else tempSurface = g_origscreen;
if(tempSurface == NULL)
tempSurface = screen; // use screen, if none available
my_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, tempSurface->w, tempSurface->h, tempSurface->format->BitsPerPixel, 0, 0, 0, 0);
if(tempSurface->format->palette && my_screen->format->palette)
SDL_SetColors(my_screen, tempSurface->format->palette->colors,
0, tempSurface->format->palette->ncolors);
surface_fader(my_screen, 0.2F, 0.2F, 0.2F, -1, 0); // fade it out to 20% of normal
SDL_BlitSurface(tempSurface, NULL, my_screen, NULL);
while(true)
{
SDL_BlitSurface(my_screen, NULL, screen, NULL); // show background
font_print_centered(sx/2 ,5*facy , incoming_dir, screen, 1.5*facx, 1.3*facy);
if (slot == 6) font_print_centered(sx/2,20*facy,"Choose image for floppy 140KB drive", screen, 1*facx, 1*facy);
else
if (slot == 7) font_print_centered(sx/2,20*facy,"Choose image for Hard Disk", screen, 1*facx, 1*facy);
else
if (slot == 5) font_print_centered(sx/2,20*facy,"Choose image for floppy 800KB drive", screen, 1*facx, 1*facy);
else
if (slot == 1) font_print_centered(sx/2,20*facy,"Select file name for saving snapshot", screen, 1*facx, 1*facy);
else
if (slot == 0) font_print_centered(sx/2,20*facy,"Select snapshot file name for loading", screen, 1*facx, 1*facy);
font_print_centered(sx/2,30*facy, "Press ENTER to choose, or ESC to cancel",screen, 1.4*facx, 1.1*facy);
files.Rewind(); // from start
sizes.Rewind();
i = 0;
// printf("We've printed some messages, go to file list!\n");
// show all fetched dirs and files
// topX of first fiel visible
int TOPX = int(45*facy);
while(files.Iterate(tmp)) {
sizes.Iterate(siz); // also fetch size string
if (i >= first_file && i < first_file + FILES_IN_SCREEN)
{ // FILES_IN_SCREEN items on screen
// char tmp2[80],tmp3[256];
if (i == act_file) { // show item under cursor (in inverse mode)
SDL_Rect r;
r.x= 2;
r.y= TOPX + (i-first_file) * 15 * facy - 1;
if(strlen(tmp) > 46) r.w = 46 * 6 * 1.7 * facx + 2;
else r.w= strlen(tmp) * 6 * 1.7 * facx + 2; // 6- FONT_SIZE_X
r.h= 9 * 1.5 * facy;
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format,255,0,0));// in RED
} /* if */
// print file name with enlarged font
char ch;
ch = 0;
if(strlen(tmp) > 46) { ch = tmp[46]; tmp[46] = 0;} //cut-off too long string
font_print(4, TOPX + (i - first_file) * 15 * facy, tmp, screen, 1.7*facx, 1.5*facy); // show name
font_print(sx - 70 * facx, TOPX + (i - first_file) * 15 * facy, siz, screen, 1.7*facx, 1.5*facy);// show info (dir or size)
if(ch) tmp[46] = ch; //restore cut-off char
} /* if */
i++; // next item
} /* while */
/////////////////////////////////////////////////////////////////////////////////////////////
// draw rectangles
rectangle(screen, 0, TOPX - 5, sx, 320*facy, SDL_MapRGB(screen->format, 255, 255, 255));
rectangle(screen, 480*facx, TOPX - 5, 0, 320*facy, SDL_MapRGB(screen->format, 255, 255, 255));
SDL_Flip(screen); // show the screen
SDL_Delay(KEY_DELAY); // wait some time to be not too fast
//////////////////////////////////
// Wait for keypress
//////////////////////////////////
SDL_Event event; // event
Uint8 *keyboard; // key state
event.type = SDL_QUIT;
while(event.type != SDL_KEYDOWN) { // wait for key pressed
SDL_Delay(10);
SDL_PollEvent(&event);
}
// control cursor
keyboard = SDL_GetKeyState(NULL); // get current state of pressed (and not pressed) keys
if (keyboard[SDLK_UP] || keyboard[SDLK_LEFT]) {
if (act_file>0) act_file--; // up one position
if (act_file<first_file) first_file=act_file;
} /* if */
if (keyboard[SDLK_DOWN] || keyboard[SDLK_RIGHT]) {
if (act_file < (files.Length() - 1)) act_file++;
if (act_file >= (first_file + FILES_IN_SCREEN)) first_file=act_file - FILES_IN_SCREEN + 1;
} /* if */
if (keyboard[SDLK_PAGEUP]) {
act_file-=FILES_IN_SCREEN;
if (act_file<0) act_file=0;
if (act_file<first_file) first_file=act_file;
} /* if */
if (keyboard[SDLK_PAGEDOWN]) {
act_file+=FILES_IN_SCREEN;
if (act_file>=files.Length()) act_file=(files.Length()-1);
if (act_file>=(first_file+FILES_IN_SCREEN)) first_file=act_file-FILES_IN_SCREEN + 1;
} /* if */
// choose an item?
if (keyboard[SDLK_RETURN]) {
// dup string from selected file name
*filename = strdup(files[act_file]);
// printf("files[act_file]=%s, *filename=%s\n\n", files[act_file], *filename);
if(!strcmp(sizes[act_file], "<DIR>") || !strcmp(sizes[act_file], "<UP>"))
*isdir = true;
else *isdir = false; // this is directory (catalog in Apple][ terminology)
*index_file = act_file; // remember current index
files.Delete();
sizes.Delete();
SDL_FreeSurface(my_screen);
return true;
} /* if */
if (keyboard[SDLK_ESCAPE]) {
files.Delete();
sizes.Delete();
SDL_FreeSurface(my_screen);
return false; // ESC has been pressed
} /* if */
if (keyboard[SDLK_HOME]) { // HOME?
act_file=0;
first_file=0;
} /* if */
if (keyboard[SDLK_END]) { // END?
act_file=files.Length() - 1; // go to the last possible file in list
first_file=act_file - FILES_IN_SCREEN + 1;
if(first_file < 0) first_file = 0;
} /* if */
}
} /* ChooseAnImage */