#include <os.h>
#include "filebrowser.h"
#include "output.h"
#include "menu.h"
#define DIR_HEIGHT (CHAR_HEIGHT + 10)
#define DIR_DIRLIST_DIST CHAR_HEIGHT
#define FILENAME_WIDTH 200
#define FILEDATE_WIDTH 0
#define FILESIZE_WIDTH (SCREEN_WIDTH - FILENAME_WIDTH - FILEDATE_WIDTH)
#define FILES_SHOWN ((SCREEN_HEIGHT - DIR_HEIGHT) / CHAR_HEIGHT)
#define MENU_SELECTION_COLOR (has_colors?0b011101111111111:0x0)
//TODO: display long directory names correctly
//some parts are adapted from hoffa's code
int is_dir(const char *path) {
struct stat filestat;
stat(path, &filestat);
printf("%s %i", path, filestat.st_mode);
return S_ISDIR(filestat.st_mode);
}
void get_filesize(const char *path, char* buffer){
struct stat filestat;
stat(path, &filestat);
int size = filestat.st_size;
const char units[4][3] = {"B\0", "kB\0", "MB\0", "GB\0"};
int i = 0;
while (size >= 1024) {
size /= 1024;
++i;
}
sprintf(buffer, "%d%s", size + 1, units[i]);
}
int get_filenames(const char* folder, char** result){
DIR* dp;
struct dirent* entryp;
int i = 0;
if((dp = opendir(folder)) == NULL){
printf("opendir error\n");
return 1;
}
while((entryp = readdir(dp)) != NULL){
char* dirname = (char*) malloc(strlen(entryp->d_name)+1);
strcpy(dirname, entryp->d_name);
result[i] = dirname;
i++;
}
return i;
}
int filebrowser(uint8_t* scrbuf, char* file){
char currentdir[FILENAME_MAX];
char* filenames[1024];
int num_files;
int filescroll = 0;
int fileselected = 0;
int i;
NU_Current_Dir("A:", currentdir);
num_files = get_filenames(currentdir, filenames);
while(1){
//disp:
memset(scrbuf, 0xFF, SCREEN_BYTES_SIZE);
dispHorizLine(scrbuf, 0, DIR_HEIGHT-1, 320, 0);
dispString(scrbuf, 4, (DIR_HEIGHT-CHAR_HEIGHT)/2, currentdir);
for(i = filescroll; i < filescroll + FILES_SHOWN && i < num_files; i++){
//disp file symbol
if(is_dir(filenames[i]) && strcmp(filenames[i], ".") && strcmp(filenames[i], ".."))
putChar(scrbuf, CHAR_WIDTH*2, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, '\\');
//disp filename, filesize and selection
if(i != fileselected){
dispString(scrbuf, CHAR_WIDTH*3, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, filenames[i]);
if(!is_dir(filenames[i])){
char size[10];
get_filesize(filenames[i], size);
dispString(scrbuf, FILENAME_WIDTH, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, size);
}
}
else{
filledRect(scrbuf, CHAR_WIDTH*3, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT-1, SCREEN_WIDTH - CHAR_WIDTH*4, CHAR_HEIGHT+2, MENU_SELECTION_COLOR);
dispStringColor(scrbuf, CHAR_WIDTH*3, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, filenames[i], has_colors?0xFFFF:0xF, MENU_SELECTION_COLOR);
if(!is_dir(filenames[i])){
char size[10];
get_filesize(filenames[i], size);
dispStringColor(scrbuf, FILENAME_WIDTH, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, size, has_colors ? 0xFFFF : 0xF, MENU_SELECTION_COLOR);
}
}
}
memcpy(SCREEN_BASE_ADDRESS, scrbuf, SCREEN_BYTES_SIZE);
//input:
if(isKeyPressed(KEY_NSPIRE_ESC))
break;
if(isKeyPressed(KEY_NSPIRE_ENTER)){
if(is_dir(filenames[fileselected])){
chdir(filenames[fileselected]);
filescroll = 0;
fileselected = 0;
NU_Current_Dir("A:", currentdir);
for(i = 0; i < num_files; i++)
free(filenames[i]);
num_files = get_filenames(currentdir, filenames);
}
else{
strcpy(file, filenames[fileselected]);
for(i = 0; i < num_files; i++)
free(filenames[i]);
return 0;
}
}
if(isKeyPressed(KEY_NSPIRE_UP)){
fileselected--;
if(fileselected < 0){
fileselected = num_files - 1;
filescroll = num_files - FILES_SHOWN;
if(filescroll < 0)
filescroll = 0;
}
else if(fileselected - filescroll < 0)
filescroll--;
}
if(isKeyPressed(KEY_NSPIRE_DOWN)){
fileselected++;
if(fileselected >= num_files){
fileselected = 0;
filescroll = 0;
}
else if(fileselected - filescroll >= FILES_SHOWN)
++filescroll;
}
sleep(100);
}
for(i = 0; i < num_files; i++)
free(filenames[i]);
return 1;
}