mirror of
https://github.com/joel16/VitaShell.git
synced 2024-11-23 03:39:39 +00:00
Feature/bookmarks (#487)
* wip * add symlink functions * introduce symlink drawing * remove warnings * add symlink theme * wip * better magic number compare * wip * wip * refactoring * resolve links * add theme * nested dir symlink contxt * nested symlinks with correct sel position * remove todos * wip non compiling * archive mode * resolve files * add context menu * resolve files correctly * err code * add shortcut for bookmarks * recent files * l/r switching * wip * menu changes * bookmark dialog * wip * add sort mode * recent files * dont store parent dir in recent files * clean up * recent menu entry * error msgs * code style ptr * arrow * new menu entries * remapping shortcuts * introduce symlink ext * fix symlink extension * file extension behaviour for folders * clean recent files * typo * change order of delete for recent folder * use left arrow key for shortcut not L key * skip symlink hierarchies when pressing O in bookmarks/ recent files * hide new bookmark entry when bookmark folder selected
This commit is contained in:
parent
4364101491
commit
8eff0e6bba
146
file.c
146
file.c
@ -45,6 +45,8 @@ static char *devices[] = {
|
||||
|
||||
#define N_DEVICES (sizeof(devices) / sizeof(char **))
|
||||
|
||||
const char symlink_header_bytes[SYMLINK_HEADER_SIZE] = {0xF1, 0x1E, 0x00, 0x00};
|
||||
|
||||
int allocateReadFile(const char *file, void **buffer) {
|
||||
SceUID fd = sceIoOpen(file, SCE_O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
@ -965,6 +967,7 @@ int fileListGetDeviceEntries(FileList *list) {
|
||||
strcpy(entry->name, devices[i]);
|
||||
entry->is_folder = 1;
|
||||
entry->type = FILE_TYPE_UNKNOWN;
|
||||
entry->is_symlink = 0;
|
||||
|
||||
SceIoDevInfo info;
|
||||
memset(&info, 0, sizeof(SceIoDevInfo));
|
||||
@ -981,9 +984,9 @@ int fileListGetDeviceEntries(FileList *list) {
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&entry->ctime, (SceDateTime *)&stat.st_ctime, sizeof(SceDateTime));
|
||||
memcpy(&entry->mtime, (SceDateTime *)&stat.st_mtime, sizeof(SceDateTime));
|
||||
memcpy(&entry->atime, (SceDateTime *)&stat.st_atime, sizeof(SceDateTime));
|
||||
memcpy(&entry->ctime, (SceDateTime *) &stat.st_ctime, sizeof(SceDateTime));
|
||||
memcpy(&entry->mtime, (SceDateTime *) &stat.st_mtime, sizeof(SceDateTime));
|
||||
memcpy(&entry->atime, (SceDateTime *) &stat.st_atime, sizeof(SceDateTime));
|
||||
|
||||
fileListAddEntry(list, entry, SORT_BY_NAME);
|
||||
|
||||
@ -1011,6 +1014,7 @@ int fileListGetDirectoryEntries(FileList *list, const char *path, int sort) {
|
||||
strcpy(entry->name, DIR_UP);
|
||||
entry->is_folder = 1;
|
||||
entry->type = FILE_TYPE_UNKNOWN;
|
||||
entry->is_symlink = 0;
|
||||
fileListAddEntry(list, entry, sort);
|
||||
}
|
||||
|
||||
@ -1025,6 +1029,9 @@ int fileListGetDirectoryEntries(FileList *list, const char *path, int sort) {
|
||||
FileListEntry *entry = malloc(sizeof(FileListEntry));
|
||||
if (entry) {
|
||||
entry->is_folder = SCE_S_ISDIR(dir.d_stat.st_mode);
|
||||
entry->is_symlink = 0;
|
||||
entry->symlink = NULL;
|
||||
|
||||
if (entry->is_folder) {
|
||||
entry->name_length = strlen(dir.d_name) + 1;
|
||||
entry->name = malloc(entry->name_length + 1);
|
||||
@ -1038,13 +1045,34 @@ int fileListGetDirectoryEntries(FileList *list, const char *path, int sort) {
|
||||
strcpy(entry->name, dir.d_name);
|
||||
entry->type = getFileType(entry->name);
|
||||
list->files++;
|
||||
|
||||
if (dir.d_stat.st_size <= SYMLINK_MAX_SIZE) {
|
||||
char *p = malloc(strlen(path) + strlen(dir.d_name) + 2);
|
||||
if (!p) {
|
||||
return VITASHELL_ERROR_INTERNAL;
|
||||
}
|
||||
snprintf(p, MAX_PATH_LENGTH - 1, "%s%s%s",
|
||||
path, hasEndSlash(path) ? "" : "/", dir.d_name);
|
||||
|
||||
Symlink* symlink = malloc(sizeof(Symlink));
|
||||
if (!symlink) {
|
||||
return VITASHELL_ERROR_INTERNAL;
|
||||
}
|
||||
int res = resolveSimLink(symlink, p);
|
||||
if (res < 0) {
|
||||
if (symlink)
|
||||
free(symlink);
|
||||
} else {
|
||||
entry->is_symlink = 1;
|
||||
entry->symlink = symlink;
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
entry->size = dir.d_stat.st_size;
|
||||
|
||||
memcpy(&entry->ctime, (SceDateTime *)&dir.d_stat.st_ctime, sizeof(SceDateTime));
|
||||
memcpy(&entry->mtime, (SceDateTime *)&dir.d_stat.st_mtime, sizeof(SceDateTime));
|
||||
memcpy(&entry->atime, (SceDateTime *)&dir.d_stat.st_atime, sizeof(SceDateTime));
|
||||
memcpy(&entry->ctime, (SceDateTime *) &dir.d_stat.st_ctime, sizeof(SceDateTime));
|
||||
memcpy(&entry->mtime, (SceDateTime *) &dir.d_stat.st_mtime, sizeof(SceDateTime));
|
||||
memcpy(&entry->atime, (SceDateTime *) &dir.d_stat.st_atime, sizeof(SceDateTime));
|
||||
|
||||
fileListAddEntry(list, entry, sort);
|
||||
}
|
||||
@ -1070,3 +1098,107 @@ int fileListGetEntries(FileList *list, const char *path, int sort) {
|
||||
|
||||
return fileListGetDirectoryEntries(list, path, sort);
|
||||
}
|
||||
|
||||
// returns < 0 on error
|
||||
int resolveSimLink(Symlink *symlink, const char *path) {
|
||||
SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return VITASHELL_ERROR_SYMLINK_INTERNAL;
|
||||
char magic[SYMLINK_HEADER_SIZE + 1];
|
||||
magic[SYMLINK_HEADER_SIZE] = '\0';
|
||||
|
||||
if (sceIoRead(fd, &magic, SYMLINK_HEADER_SIZE) < SYMLINK_HEADER_SIZE) {
|
||||
sceIoClose(fd);
|
||||
return VITASHELL_ERROR_SYMLINK_INTERNAL;
|
||||
}
|
||||
if(memcmp(magic, symlink_header_bytes, SYMLINK_HEADER_SIZE) != 0) {
|
||||
sceIoClose(fd);
|
||||
return VITASHELL_ERROR_SYMLINK_INTERNAL;
|
||||
}
|
||||
char *resolve = (char *) malloc(MAX_PATH_LENGTH);
|
||||
if (!resolve) {
|
||||
sceIoClose(fd);
|
||||
return VITASHELL_ERROR_INTERNAL;
|
||||
}
|
||||
int bytes_read = sceIoRead(fd, resolve, MAX_PATH_LENGTH - 1);
|
||||
sceIoClose(fd);
|
||||
|
||||
if (bytes_read <= 0) {
|
||||
free(resolve);
|
||||
return VITASHELL_ERROR_SYMLINK_INTERNAL;
|
||||
}
|
||||
resolve[bytes_read] = '\0';
|
||||
SceIoStat io_stat;
|
||||
memset(&io_stat, 0, sizeof(SceIoStat));
|
||||
if (sceIoGetstat(resolve, &io_stat) < 0) {
|
||||
free(resolve);
|
||||
return VITASHELL_ERROR_SYMLINK_INTERNAL;
|
||||
}
|
||||
symlink->to_file = !SCE_S_ISDIR(io_stat.st_mode);
|
||||
symlink->target_path = resolve;
|
||||
symlink->target_path_length = bytes_read + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return < 0 on error
|
||||
int createSymLink(const char *store_location, const char *target) {
|
||||
SceUID fd = sceIoOpen(store_location, SCE_O_WRONLY | SCE_O_CREAT, 0777);
|
||||
if (fd < 0) {
|
||||
return VITASHELL_ERROR_SYMLINK_INTERNAL;
|
||||
}
|
||||
sceIoWrite(fd, (void*) &symlink_header_bytes, SYMLINK_HEADER_SIZE);
|
||||
sceIoWrite(fd, (void*) target, strnlen(target, MAX_PATH_LENGTH));
|
||||
sceIoClose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get directory path from filename
|
||||
// result has slash at the end
|
||||
char * getBaseDirectory(const char * path) {
|
||||
int i;
|
||||
int sep_ind = -1;
|
||||
int len = strlen(path);
|
||||
if (len > MAX_PATH_LENGTH - 1 || len <= 0) return NULL;
|
||||
for(i = len - 1; i >=0; i --) {
|
||||
if (path[i] == '/' || path[i] == ':') {
|
||||
sep_ind = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sep_ind == -1) return NULL;
|
||||
|
||||
char * res = (char *) malloc(MAX_PATH_LENGTH);
|
||||
if (!res) return NULL;
|
||||
|
||||
strncpy(res, path, MAX_PATH_LENGTH);
|
||||
res[sep_ind + 1] = '\0';
|
||||
return res;
|
||||
}
|
||||
|
||||
// returns NULL when no filename found or error
|
||||
// result is at most MAX_PATH_LEN
|
||||
char * getFilename(const char *path) {
|
||||
int i;
|
||||
int sep_ind = -1;
|
||||
int len = strlen(path);
|
||||
if (len > MAX_PATH_LENGTH || len <= 0) return NULL;
|
||||
if (path[len - 1] == '/' || path[len - 1] == ':') return NULL; // no file
|
||||
|
||||
for(i = len - 1; i >=0; i --) {
|
||||
if (path[i] == '/' || path[i] == ':') {
|
||||
sep_ind = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sep_ind == -1) return NULL;
|
||||
char * res = (char *) malloc(MAX_PATH_LENGTH);
|
||||
if (!res) return NULL;
|
||||
|
||||
int new_len = len - (sep_ind + 1);
|
||||
strncpy(res, path + (sep_ind + 1), new_len); // dont copy separation char
|
||||
if (new_len + 1 < MAX_PATH_LENGTH)
|
||||
res[new_len] = '\0';
|
||||
else
|
||||
res[MAX_PATH_LENGTH - 1] = '\0';
|
||||
return res;
|
||||
}
|
21
file.h
21
file.h
@ -34,6 +34,12 @@
|
||||
#define HOME_PATH "home"
|
||||
#define DIR_UP ".."
|
||||
|
||||
#define SYMLINK_HEADER_SIZE 4
|
||||
#define SYMLINK_MAX_SIZE (SYMLINK_HEADER_SIZE + MAX_PATH_LENGTH)
|
||||
#define SYMLINK_EXT "lnk"
|
||||
extern const char symlink_header_bytes[SYMLINK_HEADER_SIZE];
|
||||
|
||||
|
||||
enum FileTypes {
|
||||
FILE_TYPE_UNKNOWN,
|
||||
FILE_TYPE_ARCHIVE,
|
||||
@ -63,6 +69,12 @@ enum FileMoveFlags {
|
||||
MOVE_REPLACE = 0x2, // Replace files
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int to_file; // 1: to file, 0: to directory
|
||||
char *target_path;
|
||||
int target_path_length;
|
||||
} Symlink;
|
||||
|
||||
typedef struct {
|
||||
uint64_t *value;
|
||||
uint64_t max;
|
||||
@ -77,6 +89,8 @@ typedef struct FileListEntry {
|
||||
int name_length;
|
||||
int is_folder;
|
||||
int type;
|
||||
int is_symlink;
|
||||
Symlink *symlink;
|
||||
SceOff size;
|
||||
SceOff size2;
|
||||
SceDateTime ctime;
|
||||
@ -101,6 +115,10 @@ int WriteFile(const char *file, const void *buf, int size);
|
||||
int checkFileExist(const char *file);
|
||||
int checkFolderExist(const char *folder);
|
||||
|
||||
|
||||
char * getBaseDirectory(const char *path);
|
||||
char * getFilename(const char *path);
|
||||
|
||||
int getFileSize(const char *file);
|
||||
int getFileSha1(const char *file, uint8_t *pSha1Out, FileProcessParam *param);
|
||||
int getPathInfo(const char *path, uint64_t *size, uint32_t *folders, uint32_t *files, int (* handler)(const char *path));
|
||||
@ -127,4 +145,7 @@ void fileListEmpty(FileList *list);
|
||||
|
||||
int fileListGetEntries(FileList *list, const char *path, int sort);
|
||||
|
||||
int resolveSimLink(Symlink* symlink, const char *target);
|
||||
int createSymLink(const char *source_location, const char *target);
|
||||
|
||||
#endif
|
||||
|
25
init.c
25
init.c
@ -48,6 +48,8 @@ INCLUDE_EXTERN_RESOURCE(default_pause_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_play_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_sfo_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_text_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_file_symlink_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_folder_symlink_icon_png);
|
||||
|
||||
INCLUDE_EXTERN_RESOURCE(electron_colors_txt);
|
||||
INCLUDE_EXTERN_RESOURCE(electron_archive_icon_png);
|
||||
@ -106,7 +108,9 @@ static DefaultFile default_files[] = {
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/fastforward.png", default_fastforward_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/fastrewind.png", default_fastrewind_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/file_icon.png", default_file_icon_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/file_symlink_icon.png",default_file_symlink_icon_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/folder_icon.png", default_folder_icon_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/folder_symlink_icon.png",default_folder_symlink_icon_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/ftp.png", default_ftp_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/image_icon.png", default_image_icon_png, 1),
|
||||
DEFAULT_FILE("ux0:VitaShell/theme/Default/pause.png", default_pause_png, 1),
|
||||
@ -391,6 +395,27 @@ void initVitaShell() {
|
||||
taiStopUnloadKernelModule(kernel_modid, 0, NULL, 0, NULL, NULL);
|
||||
}
|
||||
user_modid = sceKernelLoadStartModule("ux0:VitaShell/module/user.suprx", 0, NULL, 0, NULL, NULL);
|
||||
|
||||
// clear up recent folder frequently
|
||||
SceIoStat stat;
|
||||
SceDateTime now;
|
||||
sceRtcGetCurrentClock(&now, 0);
|
||||
int res = sceIoGetstat(VITASHELL_RECENT_PATH, &stat);
|
||||
if (res >= 0) {
|
||||
if (now.year * 365 + now.day - stat.st_ctime.year * 365 - stat.st_ctime.day
|
||||
>= VITASHELL_RECENT_PATH_DELETE_INTERVAL_DAYS) {
|
||||
removePath(VITASHELL_RECENT_PATH, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkFolderExist(VITASHELL_BOOKMARKS_PATH)) {
|
||||
sceIoMkdir(VITASHELL_BOOKMARKS_PATH, 0777);
|
||||
}
|
||||
if (!checkFolderExist(VITASHELL_RECENT_PATH)) {
|
||||
sceIoMkdir(VITASHELL_RECENT_PATH, 0777);
|
||||
}
|
||||
time_last_recent_files = 0;
|
||||
time_last_bookmars = 0;
|
||||
}
|
||||
|
||||
void finishVitaShell() {
|
||||
|
@ -132,6 +132,11 @@ void loadLanguage(int id) {
|
||||
LANGUAGE_ENTRY(SEND),
|
||||
LANGUAGE_ENTRY(RECEIVE),
|
||||
LANGUAGE_ENTRY(MORE),
|
||||
LANGUAGE_ENTRY(BOOKMARKS),
|
||||
LANGUAGE_ENTRY(ADHOC_TRANSFER),
|
||||
LANGUAGE_ENTRY(BOOKMARKS_SHOW),
|
||||
LANGUAGE_ENTRY(BOOKMARKS_NEW),
|
||||
LANGUAGE_ENTRY(RECENT_FILES_SHOW),
|
||||
LANGUAGE_ENTRY(COMPRESS),
|
||||
LANGUAGE_ENTRY(INSTALL_ALL),
|
||||
LANGUAGE_ENTRY(INSTALL_FOLDER),
|
||||
@ -276,6 +281,7 @@ void loadLanguage(int id) {
|
||||
LANGUAGE_ENTRY(ARCHIVE_NAME),
|
||||
LANGUAGE_ENTRY(COMPRESSION_LEVEL),
|
||||
LANGUAGE_ENTRY(ENTER_PASSWORD),
|
||||
LANGUAGE_ENTRY(BOOKMARK_CREATED)
|
||||
};
|
||||
|
||||
// Load default config file
|
||||
|
@ -91,6 +91,11 @@ enum LanguageContainer {
|
||||
SEND,
|
||||
RECEIVE,
|
||||
MORE,
|
||||
ADHOC_TRANSFER,
|
||||
BOOKMARKS,
|
||||
BOOKMARKS_SHOW,
|
||||
BOOKMARKS_NEW,
|
||||
RECENT_FILES_SHOW,
|
||||
COMPRESS,
|
||||
INSTALL_ALL,
|
||||
INSTALL_FOLDER,
|
||||
@ -235,6 +240,7 @@ enum LanguageContainer {
|
||||
ARCHIVE_NAME,
|
||||
COMPRESSION_LEVEL,
|
||||
ENTER_PASSWORD,
|
||||
BOOKMARK_CREATED,
|
||||
|
||||
LANGUAGE_CONTAINER_SIZE,
|
||||
};
|
||||
|
339
main.c
339
main.c
@ -70,6 +70,7 @@ static int dir_level = 0;
|
||||
|
||||
// Modes
|
||||
int sort_mode = SORT_BY_NAME;
|
||||
int last_set_sort_mode = SORT_BY_NAME;
|
||||
int copy_mode = COPY_MODE_NORMAL;
|
||||
int file_type = FILE_TYPE_UNKNOWN;
|
||||
|
||||
@ -96,6 +97,44 @@ int SCE_CTRL_ENTER = SCE_CTRL_CROSS, SCE_CTRL_CANCEL = SCE_CTRL_CIRCLE;
|
||||
|
||||
// Use custom config
|
||||
int use_custom_config = 1;
|
||||
SceInt64 time_last_recent_files, time_last_bookmars;
|
||||
|
||||
static void setFocusOnFilename(const char *name);
|
||||
static void fileBrowserHandleSymlink(FileListEntry* file_entry);
|
||||
static void fileBrowserHandleFolder(FileListEntry* file_entry);
|
||||
static void fileBrowserHandleFile(FileListEntry* file_entry);
|
||||
|
||||
static void create_recent_symlink(FileListEntry *file_entry);
|
||||
|
||||
static void delete_all_symlink_directory_path();
|
||||
|
||||
// escape from dir hierarchy with a symlink
|
||||
typedef struct SymlinkDirectoryPath {
|
||||
struct SymlinkDirectoryPath* previous;
|
||||
// contains / at the end, is directory where jumped from
|
||||
char last_path[MAX_PATH_LENGTH];
|
||||
// contains / at the end, is directory where jumped to
|
||||
char last_hook[MAX_PATH_LENGTH];
|
||||
} SymlinkDirectoryPath;
|
||||
|
||||
static SymlinkDirectoryPath* symlink_directory_path = NULL;
|
||||
static SymlinkDirectoryPath* symlink_directory_path_head = NULL;
|
||||
|
||||
static void storeSymlinkPath(SymlinkDirectoryPath * path) {
|
||||
if (!symlink_directory_path) {
|
||||
symlink_directory_path = path;
|
||||
symlink_directory_path_head = path;
|
||||
symlink_directory_path->previous = 0;
|
||||
} else {
|
||||
SymlinkDirectoryPath *prev = symlink_directory_path;
|
||||
symlink_directory_path = path;
|
||||
symlink_directory_path->previous = prev;
|
||||
}
|
||||
}
|
||||
|
||||
static void delete_all_symlink_directory_path() {
|
||||
|
||||
}
|
||||
|
||||
int getDialogStep() {
|
||||
sceKernelLockLwMutex(&dialog_mutex, 1, NULL);
|
||||
@ -132,6 +171,45 @@ void dirUpCloseArchive() {
|
||||
}
|
||||
}
|
||||
|
||||
int change_to_directory(char *lastdir) {
|
||||
if (!checkFolderExist(lastdir)) {
|
||||
return VITASHELL_ERROR_NAVIGATION;
|
||||
} else {
|
||||
if (isInArchive()) {
|
||||
dirUpCloseArchive();
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < strlen(lastdir) + 1; i++) {
|
||||
if (lastdir[i] == ':' || lastdir[i] == '/') {
|
||||
char ch = lastdir[i + 1];
|
||||
lastdir[i + 1] = '\0';
|
||||
|
||||
char ch2 = lastdir[i];
|
||||
lastdir[i] = '\0';
|
||||
|
||||
char *p = strrchr(lastdir, '/');
|
||||
if (!p)
|
||||
p = strrchr(lastdir, ':');
|
||||
if (!p)
|
||||
p = lastdir - 1;
|
||||
|
||||
lastdir[i] = ch2;
|
||||
|
||||
refreshFileList();
|
||||
setFocusOnFilename(p + 1);
|
||||
|
||||
strcpy(file_list.path, lastdir);
|
||||
|
||||
lastdir[i + 1] = ch;
|
||||
|
||||
dirLevelUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
refreshFileList();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dirUp() {
|
||||
if (pfs_mounted_path[0] &&
|
||||
strcmp(file_list.path, pfs_mounted_path) == 0 && // we're about to leave the pfs path
|
||||
@ -140,10 +218,36 @@ static void dirUp() {
|
||||
pfsUmount();
|
||||
}
|
||||
|
||||
// skip all symlink hierarchies when pressing O in bookmarks/ recent files
|
||||
if (symlink_directory_path_head &&
|
||||
((strncmp(file_list.path, VITASHELL_BOOKMARKS_PATH, MAX_PATH_LENGTH) == 0)
|
||||
|| strncmp(file_list.path, VITASHELL_RECENT_PATH, MAX_PATH_LENGTH) == 0)) {
|
||||
strcpy(file_list.path, symlink_directory_path_head->last_path);
|
||||
SymlinkDirectoryPath *e = symlink_directory_path;
|
||||
while(e != NULL) {
|
||||
SymlinkDirectoryPath *prev = e->previous;
|
||||
free(e);
|
||||
dir_level--;
|
||||
e = prev;
|
||||
}
|
||||
symlink_directory_path_head = 0;
|
||||
symlink_directory_path = 0;
|
||||
goto DIR_UP_RETURN;
|
||||
}
|
||||
|
||||
if (symlink_directory_path
|
||||
&& strncmp(file_list.path, symlink_directory_path->last_hook, MAX_PATH_LENGTH) == 0) {
|
||||
strcpy(file_list.path, symlink_directory_path->last_path);
|
||||
SymlinkDirectoryPath* prev = symlink_directory_path->previous;
|
||||
free(symlink_directory_path);
|
||||
symlink_directory_path = prev;
|
||||
dir_level--;
|
||||
goto DIR_UP_RETURN;
|
||||
}
|
||||
|
||||
removeEndSlash(file_list.path);
|
||||
|
||||
char *p;
|
||||
|
||||
p = strrchr(file_list.path, '/');
|
||||
if (p) {
|
||||
p[1] = '\0';
|
||||
@ -188,6 +292,14 @@ static void setFocusOnFilename(const char *name) {
|
||||
int refreshFileList() {
|
||||
int ret = 0, res = 0;
|
||||
|
||||
// always sort recent files by date
|
||||
char *contains = strstr(file_list.path, VITASHELL_RECENT_PATH);
|
||||
if (contains) {
|
||||
sort_mode = SORT_BY_DATE;
|
||||
} else {
|
||||
sort_mode = last_set_sort_mode;
|
||||
}
|
||||
|
||||
do {
|
||||
fileListEmpty(&file_list);
|
||||
|
||||
@ -1491,7 +1603,8 @@ static int fileBrowserMenuCtrl() {
|
||||
|
||||
// SELECT button
|
||||
if (pressed_pad[PAD_SELECT]) {
|
||||
if (vitashell_config.select_button == SELECT_BUTTON_MODE_USB && sceKernelGetModel() == SCE_KERNEL_MODEL_VITA) {
|
||||
if (vitashell_config.select_button == SELECT_BUTTON_MODE_USB &&
|
||||
sceKernelGetModel() == SCE_KERNEL_MODEL_VITA) {
|
||||
if (is_safe_mode) {
|
||||
infoDialog(language_container[EXTENDED_PERMISSIONS_REQUIRED]);
|
||||
} else {
|
||||
@ -1501,11 +1614,13 @@ static int fileBrowserMenuCtrl() {
|
||||
if (state.cable & SCE_UDCD_STATUS_CABLE_CONNECTED) {
|
||||
initUsb();
|
||||
} else {
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_CANCEL, language_container[USB_NOT_CONNECTED]);
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_CANCEL,
|
||||
language_container[USB_NOT_CONNECTED]);
|
||||
setDialogStep(DIALOG_STEP_USB_WAIT);
|
||||
}
|
||||
}
|
||||
} else if (vitashell_config.select_button == SELECT_BUTTON_MODE_FTP || sceKernelGetModel() == SCE_KERNEL_MODEL_VITATV) {
|
||||
} else if (vitashell_config.select_button == SELECT_BUTTON_MODE_FTP ||
|
||||
sceKernelGetModel() == SCE_KERNEL_MODEL_VITATV) {
|
||||
// Init FTP
|
||||
if (!ftpvita_is_initialized()) {
|
||||
int res = ftpvita_init(vita_ip, &vita_port);
|
||||
@ -1522,11 +1637,13 @@ static int fileBrowserMenuCtrl() {
|
||||
|
||||
// Dialog
|
||||
if (ftpvita_is_initialized()) {
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK_CANCEL, language_container[FTP_SERVER], vita_ip, vita_port);
|
||||
initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_OK_CANCEL, language_container[FTP_SERVER],
|
||||
vita_ip, vita_port);
|
||||
setDialogStep(DIALOG_STEP_FTP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// QR
|
||||
if (hold_pad[PAD_LTRIGGER] && hold_pad[PAD_RTRIGGER] && enabledQR()) {
|
||||
@ -1535,6 +1652,39 @@ static int fileBrowserMenuCtrl() {
|
||||
setDialogStep(DIALOG_STEP_QR);
|
||||
}
|
||||
*/
|
||||
|
||||
// bookmarks shortcut
|
||||
if (current_pad[PAD_LEFT] && current_pad[PAD_SQUARE]) {
|
||||
SceInt64 now = sceKernelGetSystemTimeWide();
|
||||
|
||||
// switching too quickly back and forth between recent and bookmarks
|
||||
// causes VS to crash
|
||||
if (now - time_last_bookmars > THRESHOLD_LAST_PAD_BOOKMARKS_WAIT) {
|
||||
if (strncmp(file_list.path, VITASHELL_BOOKMARKS_PATH, MAX_PATH_LENGTH) != 0) {
|
||||
char path[MAX_PATH_LENGTH] = VITASHELL_BOOKMARKS_PATH;
|
||||
sort_mode = last_set_sort_mode;
|
||||
jump_to_directory_track_current_path(path);
|
||||
time_last_bookmars = now;
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// recent files shortcut
|
||||
if (current_pad[PAD_LEFT] && current_pad[PAD_TRIANGLE]) {
|
||||
SceInt64 now = sceKernelGetSystemTimeWide();
|
||||
if (now - time_last_recent_files > THRESHOLD_LAST_PAD_RECENT_FILES_WAIT) {
|
||||
if (strncmp(file_list.path, VITASHELL_RECENT_PATH, MAX_PATH_LENGTH) != 0) {
|
||||
char path[MAX_PATH_LENGTH] = VITASHELL_RECENT_PATH;
|
||||
sort_mode = SORT_BY_DATE;
|
||||
jump_to_directory_track_current_path(path);
|
||||
time_last_recent_files = now;
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move
|
||||
if (hold_pad[PAD_UP] || hold2_pad[PAD_LEFT_ANALOG_UP]) {
|
||||
int old_pos = base_pos + rel_pos;
|
||||
@ -1632,10 +1782,52 @@ static int fileBrowserMenuCtrl() {
|
||||
|
||||
fileListEmpty(&mark_list);
|
||||
|
||||
// Handle file or folder
|
||||
// Handle file, symlink or folder
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
if (file_entry) {
|
||||
if (file_entry->is_folder) {
|
||||
if (file_entry->is_symlink) {
|
||||
fileBrowserHandleSymlink(file_entry);
|
||||
} else if (file_entry->is_folder) {
|
||||
fileBrowserHandleFolder(file_entry);
|
||||
} else {
|
||||
fileBrowserHandleFile(file_entry);
|
||||
create_recent_symlink(file_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
return refresh;
|
||||
}
|
||||
|
||||
static void create_recent_symlink(FileListEntry *file_entry) {
|
||||
char target[MAX_PATH_LENGTH];
|
||||
snprintf(target, MAX_PATH_LENGTH, "%s%s."SYMLINK_EXT, VITASHELL_RECENT_PATH,
|
||||
file_entry->name);
|
||||
snprintf(cur_file, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
|
||||
|
||||
// create file recent symlink
|
||||
createSymLink(target, cur_file);
|
||||
}
|
||||
|
||||
static void fileBrowserHandleFile(FileListEntry *file_entry) {
|
||||
snprintf(cur_file, MAX_PATH_LENGTH - 1, "%s%s", file_list.path, file_entry->name);
|
||||
int type = handleFile(cur_file, file_entry);
|
||||
|
||||
// Archive mode
|
||||
if (type == FILE_TYPE_ARCHIVE && getDialogStep() != DIALOG_STEP_ENTER_PASSWORD) {
|
||||
is_in_archive = 1;
|
||||
dir_level_archive = dir_level;
|
||||
|
||||
snprintf(archive_path, MAX_PATH_LENGTH - 1, "%s%s", file_list.path, file_entry->name);
|
||||
|
||||
strcat(file_list.path, file_entry->name);
|
||||
addEndSlash(file_list.path);
|
||||
|
||||
dirLevelUp();
|
||||
refreshFileList();
|
||||
}
|
||||
}
|
||||
|
||||
static void fileBrowserHandleFolder(FileListEntry *file_entry) {
|
||||
if (strcmp(file_entry->name, DIR_UP) == 0) {
|
||||
dirUp();
|
||||
} else {
|
||||
@ -1646,7 +1838,6 @@ static int fileBrowserMenuCtrl() {
|
||||
addEndSlash(file_list.path);
|
||||
strcat(file_list.path, file_entry->name);
|
||||
}
|
||||
|
||||
dirLevelUp();
|
||||
}
|
||||
|
||||
@ -1657,28 +1848,67 @@ static int fileBrowserMenuCtrl() {
|
||||
int res = refreshFileList();
|
||||
if (res < 0)
|
||||
errorDialog(res);
|
||||
} else {
|
||||
snprintf(cur_file, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
|
||||
int type = handleFile(cur_file, file_entry);
|
||||
|
||||
// Archive mode
|
||||
if (type == FILE_TYPE_ARCHIVE && getDialogStep() != DIALOG_STEP_ENTER_PASSWORD) {
|
||||
is_in_archive = 1;
|
||||
dir_level_archive = dir_level;
|
||||
|
||||
snprintf(archive_path, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
|
||||
|
||||
strcat(file_list.path, file_entry->name);
|
||||
addEndSlash(file_list.path);
|
||||
}
|
||||
|
||||
// escape from dir level structure so that parent directory is browsed
|
||||
// where this jump came from and not the hierarchically higher folder
|
||||
int jump_to_directory_track_current_path(char *path) {
|
||||
SymlinkDirectoryPath *symlink_path = malloc(sizeof(SymlinkDirectoryPath));
|
||||
if (symlink_path) {
|
||||
strncpy(symlink_path->last_path, file_list.path, MAX_PATH_LENGTH);
|
||||
strncpy(symlink_path->last_hook, path, MAX_PATH_LENGTH);
|
||||
dirLevelUp();
|
||||
int _dir_level = dir_level; // we escape from hierarchical dir level structure
|
||||
if (change_to_directory(path) < 0) {
|
||||
free(symlink_path);
|
||||
return VITASHELL_ERROR_NAVIGATION;
|
||||
}
|
||||
WriteFile(VITASHELL_LASTDIR, file_list.path, strlen(file_list.path) + 1);
|
||||
storeSymlinkPath(symlink_path);
|
||||
dir_level = _dir_level;
|
||||
refreshFileList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return refresh;
|
||||
static void fileBrowserHandleSymlink(FileListEntry *file_entry) {
|
||||
if ((file_entry->symlink->to_file == 1 && !checkFileExist(file_entry->symlink->target_path))
|
||||
|| (file_entry->symlink->to_file == 0 && !checkFolderExist(file_entry->symlink->target_path))) {
|
||||
// TODO: What if in archive?
|
||||
snprintf(cur_file, MAX_PATH_LENGTH - 1, "%s%s", file_list.path, file_entry->name);
|
||||
textViewer(cur_file);
|
||||
return;
|
||||
}
|
||||
if (file_entry->symlink->to_file == 0) {
|
||||
if (jump_to_directory_track_current_path(file_entry->symlink->target_path) < 0) {
|
||||
errorDialog(VITASHELL_ERROR_SYMLINK_INVALID_PATH);
|
||||
}
|
||||
} else {
|
||||
char *target_base_directory = getBaseDirectory(file_entry->symlink->target_path);
|
||||
if (!target_base_directory) {
|
||||
errorDialog(VITASHELL_ERROR_SYMLINK_CANT_RESOLVE_BASEDIR);
|
||||
return;
|
||||
}
|
||||
char *target_file_name = getFilename(file_entry->symlink->target_path);
|
||||
if (!target_file_name) {
|
||||
errorDialog(VITASHELL_ERROR_SYMLINK_CANT_RESOLVE_FILENAME);
|
||||
return;
|
||||
}
|
||||
if (jump_to_directory_track_current_path(target_base_directory) < 0) {
|
||||
errorDialog(VITASHELL_ERROR_SYMLINK_INVALID_PATH);
|
||||
return;
|
||||
}
|
||||
FileListEntry *resolved_file_entry = fileListFindEntry(&file_list, target_file_name);
|
||||
if (!resolved_file_entry) {
|
||||
errorDialog(VITASHELL_ERROR_SYMLINK_INVALID_PATH);
|
||||
return;
|
||||
}
|
||||
fileBrowserHandleFile(resolved_file_entry);
|
||||
dirUp();
|
||||
}
|
||||
int res = refreshFileList();
|
||||
if (res < 0)
|
||||
errorDialog(res);
|
||||
}
|
||||
|
||||
static int shellMain() {
|
||||
@ -1703,37 +1933,7 @@ static int shellMain() {
|
||||
// Last dir
|
||||
char lastdir[MAX_PATH_LENGTH];
|
||||
ReadFile(VITASHELL_LASTDIR, lastdir, sizeof(lastdir));
|
||||
|
||||
// Calculate dir positions if the dir is valid
|
||||
if (checkFolderExist(lastdir)) {
|
||||
int i;
|
||||
for (i = 0; i < strlen(lastdir) + 1; i++) {
|
||||
if (lastdir[i] == ':' || lastdir[i] == '/') {
|
||||
char ch = lastdir[i + 1];
|
||||
lastdir[i + 1] = '\0';
|
||||
|
||||
char ch2 = lastdir[i];
|
||||
lastdir[i] = '\0';
|
||||
|
||||
char *p = strrchr(lastdir, '/');
|
||||
if (!p)
|
||||
p = strrchr(lastdir, ':');
|
||||
if (!p)
|
||||
p = lastdir - 1;
|
||||
|
||||
lastdir[i] = ch2;
|
||||
|
||||
refreshFileList();
|
||||
setFocusOnFilename(p + 1);
|
||||
|
||||
strcpy(file_list.path, lastdir);
|
||||
|
||||
lastdir[i + 1] = ch;
|
||||
|
||||
dirLevelUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
change_to_directory(lastdir);
|
||||
}
|
||||
|
||||
// Refresh file list
|
||||
@ -1774,7 +1974,6 @@ static int shellMain() {
|
||||
pfsUmount(); // umount game data at resume
|
||||
refresh = REFRESH_MODE_NORMAL;
|
||||
}
|
||||
|
||||
if (refresh != REFRESH_MODE_NONE) {
|
||||
// Refresh lists
|
||||
refreshFileList();
|
||||
@ -1802,9 +2001,17 @@ static int shellMain() {
|
||||
float y = START_Y + (i * FONT_Y_SPACE);
|
||||
|
||||
vita2d_texture *icon = NULL;
|
||||
|
||||
if (file_entry->is_symlink) {
|
||||
if (file_entry->symlink->to_file) {
|
||||
color = FILE_SYMLINK_COLOR;
|
||||
icon = file_symlink_icon;
|
||||
} else {
|
||||
color = FOLDER_SYMLINK_COLOR;
|
||||
icon = folder_symlink_icon;
|
||||
}
|
||||
}
|
||||
// Folder
|
||||
if (file_entry->is_folder) {
|
||||
else if (file_entry->is_folder) {
|
||||
color = FOLDER_COLOR;
|
||||
icon = folder_icon;
|
||||
} else {
|
||||
@ -1865,8 +2072,18 @@ static int shellMain() {
|
||||
|
||||
float x = FILE_X;
|
||||
|
||||
char file_name[MAX_PATH_LENGTH];
|
||||
memset(file_name, 0, sizeof(MAX_PATH_LENGTH));
|
||||
|
||||
if (file_entry->is_symlink) {
|
||||
snprintf(file_name, MAX_PATH_LENGTH, "%s → %s",
|
||||
file_entry->name, file_entry->symlink->target_path);
|
||||
} else {
|
||||
strncpy(file_name, file_entry->name, file_entry->name_length + 1);
|
||||
file_name[file_entry->name_length] = '\0';
|
||||
}
|
||||
if (i == rel_pos) {
|
||||
int width = (int)pgf_text_width(file_entry->name);
|
||||
int width = (int)pgf_text_width(file_name);
|
||||
if (width >= MAX_NAME_WIDTH) {
|
||||
if (scroll_count < 60) {
|
||||
scroll_x = x;
|
||||
@ -1885,7 +2102,7 @@ static int shellMain() {
|
||||
}
|
||||
}
|
||||
|
||||
pgf_draw_text(x, y, color, file_entry->name);
|
||||
pgf_draw_text(x, y, color, file_name);
|
||||
|
||||
vita2d_disable_clipping();
|
||||
|
||||
|
13
main.h
13
main.h
@ -60,6 +60,11 @@
|
||||
|
||||
#define VITASHELL_LASTDIR "ux0:VitaShell/internal/lastdir.txt"
|
||||
|
||||
// needs / at the end
|
||||
#define VITASHELL_BOOKMARKS_PATH "ux0:VitaShell/bookmarks/"
|
||||
#define VITASHELL_RECENT_PATH "ux0:VitaShell/recent/"
|
||||
#define VITASHELL_RECENT_PATH_DELETE_INTERVAL_DAYS 14
|
||||
|
||||
#define VITASHELL_TITLEID "VITASHELL"
|
||||
|
||||
#define ALIGN(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
|
||||
@ -254,6 +259,13 @@ extern char archive_path[MAX_PATH_LENGTH];
|
||||
extern int base_pos, rel_pos;
|
||||
extern int sort_mode, copy_mode;
|
||||
|
||||
extern int last_set_sort_mode;
|
||||
|
||||
// minimum time to pass before shortcutting to recent files/ bookmarks via L/R keys
|
||||
extern SceInt64 time_last_recent_files, time_last_bookmars;
|
||||
#define THRESHOLD_LAST_PAD_RECENT_FILES_WAIT 1000000
|
||||
#define THRESHOLD_LAST_PAD_BOOKMARKS_WAIT 1000000
|
||||
|
||||
extern vita2d_pgf *font;
|
||||
extern char font_size_cache[256];
|
||||
|
||||
@ -276,5 +288,6 @@ int isInArchive();
|
||||
int refreshFileList();
|
||||
|
||||
void ftpvita_PROM(ftpvita_client_info_t *client);
|
||||
int jump_to_directory_track_current_path(char *path);
|
||||
|
||||
#endif
|
||||
|
244
main_context.c
244
main_context.c
@ -77,8 +77,9 @@ enum MenuMainEntrys {
|
||||
MENU_MAIN_ENTRY_PROPERTIES,
|
||||
MENU_MAIN_ENTRY_SORT_BY,
|
||||
MENU_MAIN_ENTRY_MORE,
|
||||
MENU_MAIN_ENTRY_SEND,
|
||||
MENU_MAIN_ENTRY_RECEIVE,
|
||||
MENU_MAIN_ENTRY_ADHOC,
|
||||
MENU_MAIN_ENTRY_BOOKMARKS,
|
||||
|
||||
};
|
||||
|
||||
MenuEntry menu_main_entries[] = {
|
||||
@ -93,8 +94,9 @@ MenuEntry menu_main_entries[] = {
|
||||
{ PROPERTIES, 11, 0, CTX_INVISIBLE },
|
||||
{ SORT_BY, 13, CTX_FLAG_MORE, CTX_VISIBLE },
|
||||
{ MORE, 14, CTX_FLAG_MORE, CTX_INVISIBLE },
|
||||
{ SEND, 17, 0, CTX_INVISIBLE }, // CTX_FLAG_BARRIER
|
||||
{ RECEIVE, 18, 0, CTX_INVISIBLE },
|
||||
{ ADHOC_TRANSFER, 16, CTX_FLAG_MORE, CTX_INVISIBLE },
|
||||
{ BOOKMARKS, 17, CTX_FLAG_MORE, CTX_INVISIBLE },
|
||||
|
||||
};
|
||||
|
||||
#define N_MENU_MAIN_ENTRIES (sizeof(menu_main_entries) / sizeof(MenuEntry))
|
||||
@ -113,6 +115,30 @@ MenuEntry menu_sort_entries[] = {
|
||||
|
||||
#define N_MENU_SORT_ENTRIES (sizeof(menu_sort_entries) / sizeof(MenuEntry))
|
||||
|
||||
enum MenuBookmarksEntrys {
|
||||
MENU_BOOKMARKS_SHOW_BOOKMARKS,
|
||||
MENU_BOOKMARKS_RECENT_FILES
|
||||
};
|
||||
|
||||
MenuEntry menu_bookmark_entries[] = {
|
||||
{ BOOKMARKS_SHOW, 12, 0, CTX_INVISIBLE },
|
||||
{ RECENT_FILES_SHOW, 13, 0, CTX_INVISIBLE },
|
||||
};
|
||||
|
||||
#define N_MENU_BOOKMARK_ENTRIES (sizeof(menu_bookmark_entries) / sizeof(MenuEntry))
|
||||
|
||||
enum MenuAdhocEntrys {
|
||||
MENU_ADHOC_SEND,
|
||||
MENU_ADHOC_RECEIVE
|
||||
};
|
||||
|
||||
MenuEntry menu_adhoc_entries[] = {
|
||||
{ SEND, 12, 0, CTX_INVISIBLE },
|
||||
{ RECEIVE, 13, 0, CTX_INVISIBLE },
|
||||
};
|
||||
|
||||
#define N_MENU_ADHOC_ENTRIES (sizeof(menu_adhoc_entries) / sizeof(MenuEntry))
|
||||
|
||||
enum MenuMoreEntrys {
|
||||
MENU_MORE_ENTRY_COMPRESS,
|
||||
MENU_MORE_ENTRY_INSTALL_ALL,
|
||||
@ -133,12 +159,14 @@ MenuEntry menu_more_entries[] = {
|
||||
|
||||
enum MenuNewEntrys {
|
||||
MENU_NEW_FILE,
|
||||
MENU_NEW_FOLDER
|
||||
MENU_NEW_FOLDER,
|
||||
MENU_NEW_BOOKMARK
|
||||
};
|
||||
|
||||
MenuEntry menu_new_entries[] = {
|
||||
{NEW_FILE, 10, 0, CTX_INVISIBLE},
|
||||
{NEW_FOLDER, 11, 0, CTX_INVISIBLE}
|
||||
{NEW_FOLDER, 11, 0, CTX_INVISIBLE},
|
||||
{BOOKMARKS_NEW, 12, 0, CTX_INVISIBLE}
|
||||
|
||||
};
|
||||
|
||||
@ -148,6 +176,8 @@ static int contextMenuHomeEnterCallback(int sel, void *context);
|
||||
static int contextMenuMainEnterCallback(int sel, void *context);
|
||||
static int contextMenuSortEnterCallback(int sel, void *context);
|
||||
static int contextMenuMoreEnterCallback(int sel, void *context);
|
||||
static int contextMenuBookmarksEnterCallback(int sel, void *context);
|
||||
static int contextMenuAdhocEnterCallback(int sel, void *context);
|
||||
static int contextMenuNewEnterCallback(int sel, void *context);
|
||||
|
||||
ContextMenu context_menu_home = {
|
||||
@ -186,6 +216,25 @@ ContextMenu context_menu_more = {
|
||||
.sel = -1,
|
||||
};
|
||||
|
||||
ContextMenu context_menu_bookmarks = {
|
||||
.parent = &context_menu_main,
|
||||
.entries = menu_bookmark_entries,
|
||||
.n_entries = N_MENU_BOOKMARK_ENTRIES,
|
||||
.max_width = 0.0f,
|
||||
.callback = contextMenuBookmarksEnterCallback,
|
||||
.sel = -1,
|
||||
};
|
||||
|
||||
ContextMenu context_menu_adhoc = {
|
||||
.parent = &context_menu_main,
|
||||
.entries = menu_adhoc_entries,
|
||||
.n_entries = N_MENU_ADHOC_ENTRIES,
|
||||
.max_width = 0.0f,
|
||||
.callback = contextMenuAdhocEnterCallback,
|
||||
.sel = -1,
|
||||
};
|
||||
|
||||
|
||||
ContextMenu context_menu_new = {
|
||||
.parent = &context_menu_main,
|
||||
.entries = menu_new_entries,
|
||||
@ -287,7 +336,8 @@ void initContextMenuWidth() {
|
||||
|
||||
// Main
|
||||
for (i = 0; i < N_MENU_MAIN_ENTRIES; i++) {
|
||||
context_menu_main.max_width = MAX(context_menu_main.max_width, pgf_text_width(language_container[menu_main_entries[i].name]));
|
||||
context_menu_main.max_width = MAX(context_menu_main.max_width,
|
||||
pgf_text_width(language_container[menu_main_entries[i].name]));
|
||||
|
||||
if (menu_main_entries[i].name == MARK_ALL) {
|
||||
menu_main_entries[i].name = UNMARK_ALL;
|
||||
@ -321,6 +371,26 @@ void initContextMenuWidth() {
|
||||
}
|
||||
context_menu_new.max_width += 2.0f * CONTEXT_MENU_MARGIN;
|
||||
context_menu_new.max_width = MAX(context_menu_new.max_width, CONTEXT_MENU_MIN_WIDTH);
|
||||
|
||||
// bookmarks
|
||||
for (i = 0; i < N_MENU_BOOKMARK_ENTRIES; i++) {
|
||||
context_menu_bookmarks.max_width = MAX(context_menu_bookmarks.max_width, pgf_text_width
|
||||
(language_container[menu_bookmark_entries[i].name]));
|
||||
}
|
||||
|
||||
context_menu_bookmarks.max_width += 2.0f * CONTEXT_MENU_MARGIN;
|
||||
context_menu_bookmarks.max_width = MAX(context_menu_bookmarks.max_width, CONTEXT_MENU_MIN_WIDTH);
|
||||
|
||||
// adhoc
|
||||
for (i = 0; i < N_MENU_ADHOC_ENTRIES; i++) {
|
||||
context_menu_adhoc.max_width = MAX(context_menu_adhoc.max_width, pgf_text_width
|
||||
(language_container[menu_adhoc_entries[i].name]));
|
||||
}
|
||||
|
||||
context_menu_adhoc.max_width += 2.0f * CONTEXT_MENU_MARGIN;
|
||||
context_menu_adhoc.max_width = MAX(context_menu_adhoc.max_width, CONTEXT_MENU_MIN_WIDTH);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void setContextMenuHomeVisibilities() {
|
||||
@ -415,8 +485,6 @@ void setContextMenuMainVisibilities() {
|
||||
menu_main_entries[MENU_MAIN_ENTRY_DELETE].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_RENAME].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_PROPERTIES].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_SEND].visibility = CTX_INVISIBLE;
|
||||
// menu_main_entries[MENU_MAIN_ENTRY_RECEIVE].flags = CTX_FLAG_BARRIER;
|
||||
}
|
||||
|
||||
// Invisible 'Paste' if nothing is copied yet
|
||||
@ -433,8 +501,6 @@ void setContextMenuMainVisibilities() {
|
||||
menu_main_entries[MENU_MAIN_ENTRY_DELETE].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_RENAME].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_NEW].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_SEND].visibility = CTX_INVISIBLE;
|
||||
menu_main_entries[MENU_MAIN_ENTRY_RECEIVE].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
// Mark/Unmark all text
|
||||
@ -472,6 +538,74 @@ void setContextMenuMainVisibilities() {
|
||||
context_menu_main.sel = -1;
|
||||
}
|
||||
|
||||
void setContextMenuBookmarksVisibilities() {
|
||||
int i;
|
||||
// All visible
|
||||
for (i = 0; i < N_MENU_BOOKMARK_ENTRIES; i++) {
|
||||
if (menu_bookmark_entries[i].visibility == CTX_INVISIBLE)
|
||||
menu_bookmark_entries[i].visibility = CTX_VISIBLE;
|
||||
}
|
||||
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
if (!file_entry)
|
||||
return;
|
||||
|
||||
if (strcmp(file_list.path, VITASHELL_BOOKMARKS_PATH) == 0) {
|
||||
menu_bookmark_entries[MENU_BOOKMARKS_SHOW_BOOKMARKS].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
if (strcmp(file_list.path, VITASHELL_RECENT_PATH) == 0) {
|
||||
menu_bookmark_entries[MENU_BOOKMARKS_RECENT_FILES].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
// Go to first entry
|
||||
for (i = 0; i < N_MENU_BOOKMARK_ENTRIES; i++) {
|
||||
if (menu_bookmark_entries[i].visibility == CTX_VISIBLE) {
|
||||
context_menu_bookmarks.sel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == N_MENU_BOOKMARK_ENTRIES)
|
||||
context_menu_bookmarks.sel = -1;
|
||||
|
||||
}
|
||||
void setContextMenuAdhocVisibilities() {
|
||||
int i;
|
||||
// All visible
|
||||
for (i = 0; i < N_MENU_ADHOC_ENTRIES; i++) {
|
||||
if (menu_adhoc_entries[i].visibility == CTX_INVISIBLE)
|
||||
menu_adhoc_entries[i].visibility = CTX_VISIBLE;
|
||||
}
|
||||
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
if (!file_entry)
|
||||
return;
|
||||
|
||||
// Invisble entries when on '..'
|
||||
if (strcmp(file_entry->name, DIR_UP) == 0) {
|
||||
menu_adhoc_entries[MENU_ADHOC_SEND].visibility = CTX_INVISIBLE;
|
||||
// menu_adhoc_entries[MENU_ADHOC_RECEIVE].flags = CTX_FLAG_BARRIER;
|
||||
}
|
||||
|
||||
// Invisible write operations in archives
|
||||
// TODO: read-only mount points
|
||||
if (isInArchive() || (pfs_mounted_path[0] && strstr(file_list.path, pfs_mounted_path) && read_only)) {
|
||||
menu_adhoc_entries[MENU_ADHOC_SEND].visibility = CTX_INVISIBLE;
|
||||
menu_adhoc_entries[MENU_ADHOC_RECEIVE].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
// Go to first entry
|
||||
for (i = 0; i < N_MENU_ADHOC_ENTRIES; i++) {
|
||||
if (menu_adhoc_entries[i].visibility == CTX_VISIBLE) {
|
||||
context_menu_adhoc.sel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == N_MENU_ADHOC_ENTRIES)
|
||||
context_menu_adhoc.sel = -1;
|
||||
}
|
||||
|
||||
void setContextMenuSortVisibilities() {
|
||||
int i;
|
||||
|
||||
@ -601,6 +735,21 @@ void setContextMenuNewVisibilities() {
|
||||
}
|
||||
}
|
||||
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
if (file_entry) {
|
||||
snprintf(cur_file, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
|
||||
if (strncmp(cur_file, VITASHELL_BOOKMARKS_PATH, MAX_PATH_LENGTH) == 0) {
|
||||
menu_new_entries[MENU_NEW_BOOKMARK].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
// Invisble entries when on '..'
|
||||
if (strcmp(file_entry->name, DIR_UP) == 0 || file_entry->is_symlink) {
|
||||
menu_new_entries[MENU_NEW_BOOKMARK].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
} else {
|
||||
menu_new_entries[MENU_NEW_BOOKMARK].visibility = CTX_INVISIBLE;
|
||||
}
|
||||
|
||||
|
||||
if (i == N_MENU_NEW_ENTRIES)
|
||||
context_menu_new.sel = -1;
|
||||
}
|
||||
@ -999,18 +1148,18 @@ static int contextMenuMainEnterCallback(int sel, void *context) {
|
||||
return CONTEXT_MENU_MORE_OPENING;
|
||||
}
|
||||
|
||||
case MENU_MAIN_ENTRY_SEND:
|
||||
case MENU_MAIN_ENTRY_BOOKMARKS:
|
||||
{
|
||||
initNetCheckDialog(SCE_NETCHECK_DIALOG_MODE_PSP_ADHOC_JOIN, 60 * 1000 * 1000);
|
||||
setDialogStep(DIALOG_STEP_ADHOC_SEND_NETCHECK);
|
||||
break;
|
||||
setContextMenu(&context_menu_bookmarks);
|
||||
setContextMenuBookmarksVisibilities();
|
||||
return CONTEXT_MENU_MORE_OPENING;
|
||||
}
|
||||
|
||||
case MENU_MAIN_ENTRY_RECEIVE:
|
||||
case MENU_MAIN_ENTRY_ADHOC:
|
||||
{
|
||||
initNetCheckDialog(SCE_NETCHECK_DIALOG_MODE_PSP_ADHOC_CONN, 0);
|
||||
setDialogStep(DIALOG_STEP_ADHOC_RECEIVE_NETCHECK);
|
||||
break;
|
||||
setContextMenu(&context_menu_adhoc);
|
||||
setContextMenuAdhocVisibilities();
|
||||
return CONTEXT_MENU_MORE_OPENING;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1032,11 +1181,47 @@ static int contextMenuSortEnterCallback(int sel, void *context) {
|
||||
break;
|
||||
}
|
||||
|
||||
last_set_sort_mode = sort_mode;
|
||||
|
||||
// Refresh list
|
||||
refreshFileList();
|
||||
|
||||
return CONTEXT_MENU_CLOSING;
|
||||
}
|
||||
static int contextMenuBookmarksEnterCallback(int sel, void *context) {
|
||||
switch (sel) {
|
||||
case MENU_BOOKMARKS_SHOW_BOOKMARKS:
|
||||
{
|
||||
char path[MAX_PATH_LENGTH] = VITASHELL_BOOKMARKS_PATH;
|
||||
jump_to_directory_track_current_path(path);
|
||||
break;
|
||||
}
|
||||
case MENU_BOOKMARKS_RECENT_FILES:
|
||||
{
|
||||
char path[MAX_PATH_LENGTH] = VITASHELL_RECENT_PATH;
|
||||
jump_to_directory_track_current_path(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return CONTEXT_MENU_CLOSING;
|
||||
}
|
||||
|
||||
static int contextMenuAdhocEnterCallback(int sel, void *context) {
|
||||
switch(sel) {
|
||||
case MENU_ADHOC_RECEIVE: {
|
||||
initNetCheckDialog(SCE_NETCHECK_DIALOG_MODE_PSP_ADHOC_CONN, 0);
|
||||
setDialogStep(DIALOG_STEP_ADHOC_RECEIVE_NETCHECK);
|
||||
break;
|
||||
};
|
||||
case MENU_ADHOC_SEND : {
|
||||
initNetCheckDialog(SCE_NETCHECK_DIALOG_MODE_PSP_ADHOC_JOIN, 60 * 1000 * 1000);
|
||||
setDialogStep(DIALOG_STEP_ADHOC_SEND_NETCHECK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return CONTEXT_MENU_CLOSING;
|
||||
}
|
||||
|
||||
|
||||
static int contextMenuMoreEnterCallback(int sel, void *context) {
|
||||
switch (sel) {
|
||||
@ -1156,7 +1341,6 @@ static int contextMenuMoreEnterCallback(int sel, void *context) {
|
||||
|
||||
return CONTEXT_MENU_CLOSING;
|
||||
}
|
||||
|
||||
static int contextMenuNewEnterCallback(int sel, void *context) {
|
||||
switch (sel) {
|
||||
case MENU_NEW_FILE: {
|
||||
@ -1204,6 +1388,26 @@ static int contextMenuNewEnterCallback(int sel, void *context) {
|
||||
MAX_NAME_LENGTH, SCE_IME_TYPE_BASIC_LATIN, 0, 0);
|
||||
setDialogStep(DIALOG_STEP_NEW_FOLDER);
|
||||
break;
|
||||
};
|
||||
case MENU_NEW_BOOKMARK: {
|
||||
FileListEntry *file_entry = fileListGetNthEntry(&file_list, base_pos + rel_pos);
|
||||
if (file_entry) {
|
||||
snprintf(cur_file, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name);
|
||||
char target[MAX_PATH_LENGTH];
|
||||
char name[MAX_PATH_LENGTH];
|
||||
strncpy(name, file_entry->name, MAX_PATH_LENGTH);
|
||||
removeEndSlash(name);
|
||||
snprintf(target, MAX_PATH_LENGTH, "%s%s."SYMLINK_EXT, VITASHELL_BOOKMARKS_PATH, name);
|
||||
int res;
|
||||
if ((res = createSymLink(target, cur_file)) < 0) {
|
||||
errorDialog(res);
|
||||
} else {
|
||||
infoDialog(language_container[BOOKMARK_CREATED]);
|
||||
}
|
||||
} else {
|
||||
errorDialog(-2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Refresh list
|
||||
|
@ -35,6 +35,8 @@ void initContextMenuWidth();
|
||||
void setContextMenuHomeVisibilities();
|
||||
void setContextMenuMainVisibilities();
|
||||
void setContextMenuSortVisibilities();
|
||||
void setContextMenuBookmarksVisibilities();
|
||||
void setContextMenuAdhocVisibilities();
|
||||
void setContextMenuMoreVisibilities();
|
||||
void setContextMenuNewVisibilities();
|
||||
|
||||
|
@ -24,6 +24,8 @@ ARCHIVE_COLOR = 0xFF007FFF # Orange
|
||||
SCROLL_BAR_COLOR = 0xFFFF7F00 # Azure
|
||||
SCROLL_BAR_BG_COLOR = 0xFF7F7F7F # Gray
|
||||
MARKED_COLOR = 0x4FFF7F00 # Azure with alpha
|
||||
FILE_SYMLINK_COLOR = 0xFFFFFFFF # White
|
||||
FOLDER_SYMLINK_COLOR = 0xFFFFFFFF # White
|
||||
|
||||
# Context menu colors
|
||||
CONTEXT_MENU_TEXT_COLOR = 0xFFFFFFFF # White
|
||||
|
BIN
resources/default/file_symlink_icon.png
Normal file
BIN
resources/default/file_symlink_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
resources/default/folder_symlink_icon.png
Normal file
BIN
resources/default/folder_symlink_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -81,6 +81,12 @@ EXPORT_MEDIA = "Export media"
|
||||
CUT = "Cut"
|
||||
INSERT_EMPTY_LINE = "Insert empty line"
|
||||
SEARCH = "Search"
|
||||
BOOKMARKS = "Bookmarks"
|
||||
ADHOC_TRANSFER = "Adhoc"
|
||||
BOOKMARKS_SHOW = "Show bookmarks"
|
||||
BOOKMARKS_NEW = "New bookmark"
|
||||
BOOKMARK_CREATED = "Bookmark added"
|
||||
RECENT_FILES_SHOW = "Recent files"
|
||||
|
||||
# File browser properties strings
|
||||
PROPERTY_NAME = "Name"
|
||||
|
13
theme.c
13
theme.c
@ -34,7 +34,9 @@ INCLUDE_EXTERN_RESOURCE(default_cover_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_fastforward_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_fastrewind_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_file_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_file_symlink_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_folder_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_folder_symlink_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_ftp_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_image_icon_png);
|
||||
INCLUDE_EXTERN_RESOURCE(default_pause_png);
|
||||
@ -58,6 +60,8 @@ int SETTINGS_MENU_OPTION_COLOR;
|
||||
// File browser colors
|
||||
int FOCUS_COLOR;
|
||||
int FILE_COLOR;
|
||||
int FILE_SYMLINK_COLOR;
|
||||
int FOLDER_SYMLINK_COLOR;
|
||||
int SFO_COLOR;
|
||||
int TXT_COLOR;
|
||||
int FOLDER_COLOR;
|
||||
@ -105,7 +109,8 @@ int AUDIO_TIME_TOTAL;
|
||||
int AUDIO_TIME_BAR;
|
||||
int AUDIO_TIME_BAR_BG;
|
||||
|
||||
vita2d_texture *folder_icon = NULL, *file_icon = NULL, *archive_icon = NULL, *image_icon = NULL, *audio_icon = NULL, *sfo_icon = NULL, *text_icon = NULL,
|
||||
vita2d_texture *folder_icon = NULL, *folder_symlink_icon = NULL, *file_icon = NULL,*file_symlink_icon = NULL, *archive_icon =NULL, *image_icon = NULL,
|
||||
*audio_icon = NULL, *sfo_icon = NULL, *text_icon = NULL,
|
||||
*ftp_image = NULL, *dialog_image = NULL, *context_image = NULL, *context_more_image = NULL, *settings_image = NULL, *battery_image = NULL,
|
||||
*battery_bar_red_image = NULL, *battery_bar_green_image = NULL, *battery_bar_charge_image = NULL, *bg_browser_image = NULL, *bg_hex_image = NULL, *bg_text_image = NULL,
|
||||
*bg_photo_image = NULL, *bg_audio_image = NULL, *cover_image = NULL, *play_image = NULL, *pause_image = NULL, *fastforward_image = NULL, *fastrewind_image = NULL;
|
||||
@ -142,7 +147,11 @@ ThemeImage theme_images[] = {
|
||||
{ "fastforward.png", &_binary_resources_default_fastforward_png_start, &fastforward_image },
|
||||
{ "fastrewind.png", &_binary_resources_default_fastrewind_png_start, &fastrewind_image },
|
||||
{ "file_icon.png", &_binary_resources_default_file_icon_png_start, &file_icon },
|
||||
{ "file_symlink_icon.png", &_binary_resources_default_file_symlink_icon_png_start,
|
||||
&file_symlink_icon },
|
||||
{ "folder_icon.png", &_binary_resources_default_folder_icon_png_start, &folder_icon },
|
||||
{ "folder_symlink_icon.png", &_binary_resources_default_folder_symlink_icon_png_start,
|
||||
&folder_symlink_icon },
|
||||
{ "ftp.png", &_binary_resources_default_ftp_png_start, &ftp_image },
|
||||
{ "image_icon.png", &_binary_resources_default_image_icon_png_start, &image_icon },
|
||||
{ "pause.png", &_binary_resources_default_pause_png_start, &pause_image },
|
||||
@ -174,6 +183,8 @@ void loadTheme() {
|
||||
// File browser colors
|
||||
COLOR_ENTRY(FOCUS_COLOR),
|
||||
COLOR_ENTRY(FILE_COLOR),
|
||||
COLOR_ENTRY(FILE_SYMLINK_COLOR),
|
||||
COLOR_ENTRY(FOLDER_SYMLINK_COLOR),
|
||||
COLOR_ENTRY(SFO_COLOR),
|
||||
COLOR_ENTRY(TXT_COLOR),
|
||||
COLOR_ENTRY(FOLDER_COLOR),
|
||||
|
5
theme.h
5
theme.h
@ -43,6 +43,8 @@ extern int ARCHIVE_COLOR;
|
||||
extern int SCROLL_BAR_COLOR;
|
||||
extern int SCROLL_BAR_BG_COLOR;
|
||||
extern int MARKED_COLOR;
|
||||
extern int FILE_SYMLINK_COLOR;
|
||||
extern int FOLDER_SYMLINK_COLOR;
|
||||
|
||||
// Context menu colors
|
||||
extern int CONTEXT_MENU_TEXT_COLOR;
|
||||
@ -85,7 +87,8 @@ extern int AUDIO_TIME_BAR_BG;
|
||||
extern vita2d_texture *folder_icon, *file_icon, *archive_icon, *image_icon, *audio_icon, *sfo_icon, *text_icon,
|
||||
*ftp_image, *dialog_image, *context_image, *context_more_image, *settings_image, *battery_image,
|
||||
*battery_bar_red_image, *battery_bar_green_image, *battery_bar_charge_image, *bg_browser_image, *bg_hex_image, *bg_text_image,
|
||||
*bg_photo_image, *bg_audio_image, *cover_image, *play_image, *pause_image, *fastforward_image, *fastrewind_image;
|
||||
*bg_photo_image, *bg_audio_image, *cover_image, *play_image, *pause_image,
|
||||
*fastforward_image, *fastrewind_image, *folder_symlink_icon, *file_symlink_icon;
|
||||
|
||||
extern vita2d_texture *wallpaper_image;
|
||||
extern vita2d_texture *previous_wallpaper_image, *current_wallpaper_image;
|
||||
|
@ -34,6 +34,17 @@ enum VitaShellErrors {
|
||||
VITASHELL_ERROR_DST_IS_SUBFOLDER_OF_SRC = 0xF0020001,
|
||||
|
||||
VITASHELL_ERROR_INVALID_TITLEID = 0xF0030000,
|
||||
|
||||
VITASHELL_ERROR_SYMLINK_INVALID_PATH = 0xF0040000,
|
||||
VITASHELL_ERROR_SYMLINK_CANT_RESOLVE_BASEDIR = 0xF0040001,
|
||||
VITASHELL_ERROR_SYMLINK_CANT_RESOLVE_FILENAME = 0xF0040002,
|
||||
VITASHELL_ERROR_SYMLINK_INTERNAL = 0xF0040003,
|
||||
|
||||
VITASHELL_ERROR_NAVIGATION = 0xF0050000,
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user