diff --git a/README.md b/README.md index 8e6bc85..0733245 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,14 @@ You can customize those files: - **'ux0:VitaShell/theme/YOUR_THEME_NAME/battery_bar_red.png'**: Red battery bar - **'ux0:VitaShell/theme/YOUR_THEME_NAME/battery_bar_charge.png'**: Charging battery bar - **'ux0:VitaShell/theme/YOUR_THEME_NAME/ftp.png'**: Ftp icon +- **'ux0:VitaShell/theme/YOUR_THEME_NAME/audio_icon.png'**: Audio icon - **'ux0:VitaShell/theme/YOUR_THEME_NAME/archive_icon.png'**: Archive icon - **'ux0:VitaShell/theme/YOUR_THEME_NAME/file_icon.png'**: File icon - **'ux0:VitaShell/theme/YOUR_THEME_NAME/folder_icon.png'**: Folder icon - **'ux0:VitaShell/theme/YOUR_THEME_NAME/image_icon.png'**: Image icon +- **'ux0:VitaShell/theme/YOUR_THEME_NAME/sfo_icon.png'**: SFO icon +- **'ux0:VitaShell/theme/YOUR_THEME_NAME/text_icon.png'**: Text icon + **Theme setting:** VitaShell will load the theme that is set in **'ux0:VitaShell/theme/theme.txt'** (THEME_NAME = "YOUR_THEME_NAME") diff --git a/file.c b/file.c index e5b3baa..58be87d 100644 --- a/file.c +++ b/file.c @@ -419,6 +419,24 @@ FileListEntry *fileListGetNthEntry(FileList *list, int n) { return entry; } +int fileListGetNumberByName(FileList *list, char *name) { + FileListEntry *entry = list->head; + + int name_length = strlen(name); + + int n = 0; + + while (entry) { + if (entry->name_length == name_length && strcmp(entry->name, name) == 0) + break; + + n++; + entry = entry->next; + } + + return n; +} + void fileListAddEntry(FileList *list, FileListEntry *entry, int sort) { entry->next = NULL; entry->previous = NULL; diff --git a/file.h b/file.h index 70b861b..61ce4c2 100644 --- a/file.h +++ b/file.h @@ -85,10 +85,14 @@ char **getMountPoints(); FileListEntry *fileListFindEntry(FileList *list, char *name); FileListEntry *fileListGetNthEntry(FileList *list, int n); +int fileListGetNumberByName(FileList *list, char *name); + void fileListAddEntry(FileList *list, FileListEntry *entry, int sort); int fileListRemoveEntry(FileList *list, FileListEntry *entry); int fileListRemoveEntryByName(FileList *list, char *name); + void fileListEmpty(FileList *list); + int fileListGetEntries(FileList *list, char *path); #endif diff --git a/language.c b/language.c index 5242e3c..e297428 100644 --- a/language.c +++ b/language.c @@ -89,12 +89,14 @@ void loadLanguage(int id) { LANGUAGE_ENTRY(DELETE_FILE_QUESTION), LANGUAGE_ENTRY(DELETE_FOLDER_QUESTION), LANGUAGE_ENTRY(DELETE_FILES_FOLDERS_QUESTION), + LANGUAGE_ENTRY(INSTALL_ALL_QUESTION), LANGUAGE_ENTRY(INSTALL_QUESTION), LANGUAGE_ENTRY(INSTALL_WARNING), LANGUAGE_ENTRY(SAVE_MODIFICATIONS), LANGUAGE_ENTRY(WIFI_ERROR), LANGUAGE_ENTRY(FTP_SERVER), LANGUAGE_ENTRY(SYS_INFO), + LANGUAGE_ENTRY(INSTALL_ALL), LANGUAGE_ENTRY(UPDATE_QUESTION), }; @@ -109,4 +111,4 @@ void loadLanguage(int id) { readConfig(path, language_entries, sizeof(language_entries) / sizeof(ConfigEntry)); } } -} \ No newline at end of file +} diff --git a/language.h b/language.h index f4e3610..ba005c1 100644 --- a/language.h +++ b/language.h @@ -47,12 +47,14 @@ enum LanguageContainer { DELETE_FILE_QUESTION, DELETE_FOLDER_QUESTION, DELETE_FILES_FOLDERS_QUESTION, + INSTALL_ALL_QUESTION, INSTALL_QUESTION, INSTALL_WARNING, SAVE_MODIFICATIONS, WIFI_ERROR, FTP_SERVER, SYS_INFO, + INSTALL_ALL, UPDATE_QUESTION, LANGUAGE_CONTRAINER_SIZE, }; @@ -62,4 +64,4 @@ extern char *language_container[LANGUAGE_CONTRAINER_SIZE]; void freeLanguageContainer(); void loadLanguage(int id); -#endif \ No newline at end of file +#endif diff --git a/main.c b/main.c index 8d2d481..db1176a 100644 --- a/main.c +++ b/main.c @@ -56,10 +56,10 @@ int _newlib_heap_size_user = 64 * 1024 * 1024; #define MAX_DIR_LEVELS 1024 // File lists -static FileList file_list, mark_list, copy_list; +static FileList file_list, mark_list, copy_list, install_list; // Paths -static char cur_file[MAX_PATH_LENGTH], archive_path[MAX_PATH_LENGTH]; +static char cur_file[MAX_PATH_LENGTH], archive_path[MAX_PATH_LENGTH], install_path[MAX_PATH_LENGTH]; // Position static int base_pos = 0, rel_pos = 0; @@ -149,6 +149,39 @@ DIR_UP_RETURN: dirUpCloseArchive(); } +void focusOnFilename(char *name) { + int name_pos = fileListGetNumberByName(&file_list, name); + if (name_pos < file_list.length) { + while (1) { + int index = base_pos + rel_pos; + if (index == name_pos) + break; + + if (index > name_pos) { + if (rel_pos > 0) { + rel_pos--; + } else { + if (base_pos > 0) { + base_pos--; + } + } + } + + if (index < name_pos) { + if ((rel_pos + 1) < file_list.length) { + if ((rel_pos + 1) < MAX_POSITION) { + rel_pos++; + } else { + if ((base_pos + rel_pos + 1) < file_list.length) { + base_pos++; + } + } + } + } + } + } +} + int refreshFileList() { int ret = 0, res = 0; @@ -406,7 +439,8 @@ void drawShellInfo(char *path) { } enum MenuEntrys { - MENU_ENTRY_MARK_UNMARK_ALL, + MENU_ENTRY_INSTALL_ALL, + MENU_ENTRY_MARK_UNMARK_ALL, MENU_ENTRY_EMPTY_1, MENU_ENTRY_MOVE, MENU_ENTRY_COPY, @@ -430,7 +464,8 @@ typedef struct { } MenuEntry; MenuEntry menu_entries[] = { - { MARK_ALL, VISIBILITY_INVISIBLE }, + { INSTALL_ALL, VISIBILITY_INVISIBLE }, + { MARK_ALL, VISIBILITY_INVISIBLE }, { -1, VISIBILITY_UNUSED }, { MOVE, VISIBILITY_INVISIBLE }, { COPY, VISIBILITY_INVISIBLE }, @@ -477,6 +512,10 @@ void initContextMenu() { menu_entries[MENU_ENTRY_NEW_FOLDER].visibility = VISIBILITY_INVISIBLE; } + if(file_entry->type != FILE_TYPE_VPK) { + menu_entries[MENU_ENTRY_INSTALL_ALL].visibility = VISIBILITY_INVISIBLE; + } + // TODO: Moving from one mount point to another is not possible // Mark/Unmark all text @@ -733,6 +772,37 @@ void contextMenuCtrl() { dialog_step = DIALOG_STEP_NEW_FOLDER; break; } + + case MENU_ENTRY_INSTALL_ALL: + { + // Empty install list + fileListEmpty(&install_list); + + FileListEntry *file_entry = file_list.head->next; // Ignore '..' + + int i; + for (i = 0; i < file_list.length - 1; i++) { + char path[MAX_PATH_LENGTH]; + snprintf(path, MAX_PATH_LENGTH, "%s%s", file_list.path, file_entry->name); + + int type = getFileType(path); + if (type == FILE_TYPE_VPK) { + FileListEntry *install_entry = malloc(sizeof(FileListEntry)); + memcpy(install_entry, file_entry, sizeof(FileListEntry)); + fileListAddEntry(&install_list, install_entry, SORT_NONE); + } + + // Next + file_entry = file_entry->next; + } + + strcpy(install_list.path, file_list.path); + + initMessageDialog(SCE_MSG_DIALOG_BUTTON_TYPE_YESNO, language_container[INSTALL_ALL_QUESTION]); + dialog_step = DIALOG_STEP_INSTALL_QUESTION; + + break; + } } ctx_menu_mode = CONTEXT_MENU_CLOSING; @@ -759,7 +829,6 @@ int dialogSteps() { // With refresh case DIALOG_STEP_COPIED: case DIALOG_STEP_DELETED: - case DIALOG_STEP_INSTALLED: if (msg_result == MESSAGE_DIALOG_RESULT_NONE || msg_result == MESSAGE_DIALOG_RESULT_FINISHED) { refresh = 1; dialog_step = DIALOG_STEP_NONE; @@ -908,7 +977,19 @@ int dialogSteps() { case DIALOG_STEP_INSTALL_CONFIRMED: if (msg_result == MESSAGE_DIALOG_RESULT_RUNNING) { InstallArguments args; - args.file = cur_file; + if(install_list.length > 0) { + FileListEntry *entry = install_list.head; + snprintf(install_path, MAX_PATH_LENGTH, "%s%s", install_list.path, entry->name); + args.file = install_path; + + // Focus + focusOnFilename(entry->name); + + // Remove entry + fileListRemoveEntry(&install_list, entry); + } else { + args.file = cur_file; + } SceUID thid = sceKernelCreateThread("install_thread", (SceKernelThreadEntry)install_thread, 0x40, 0x10000, 0, 0, NULL); if (thid >= 0) @@ -928,6 +1009,19 @@ int dialogSteps() { break; + case DIALOG_STEP_INSTALLED: + if (msg_result == MESSAGE_DIALOG_RESULT_NONE || msg_result == MESSAGE_DIALOG_RESULT_FINISHED) { + if(install_list.length > 0) { + initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[INSTALLING]); + dialog_step = DIALOG_STEP_INSTALL_CONFIRMED; + break; + } + + dialog_step = DIALOG_STEP_NONE; + } + + break; + case DIALOG_STEP_UPDATE_QUESTION: if (msg_result == MESSAGE_DIALOG_RESULT_YES) { initMessageDialog(MESSAGE_DIALOG_PROGRESS_BAR, language_container[DOWNLOADING]); diff --git a/resources/english_us.txt b/resources/english_us.txt index 3a0d2db..3732502 100644 --- a/resources/english_us.txt +++ b/resources/english_us.txt @@ -27,10 +27,12 @@ EXTRACTING = "Extracting..." DELETE_FILE_QUESTION = "Are you sure you want to delete this file?" DELETE_FOLDER_QUESTION = "Are you sure you want to delete this folder?" DELETE_FILES_FOLDERS_QUESTION = "Are you sure you want to delete these files/folders?" +INSTALL_ALL_QUESTION = "Do you want to install all packages available in this folder?" INSTALL_QUESTION = "Do you want to install this package?" INSTALL_WARNING = "This package requests extended permissions.\It will have access to your personal information.\If you did not obtain it from a trusted source,\please proceed at your own caution.\\Would you like to continue the install?" SAVE_MODIFICATIONS = "Do you want to save your modifications?" WIFI_ERROR = "You must use Wi-Fi to do this." FTP_SERVER = "FTP server is now running at\ftp://%s:%i\\Press 'OK' to keep it in background.\Press 'Cancel' to disconnect." SYS_INFO = "System software: %s\Model: 0x%08X\MAC address: %s\IP address: %s\Memory card: %s/%s" -UPDATE_QUESTION = "VitaShell %s is now available.\\Do you want to update the application?" \ No newline at end of file +INSTALL_ALL = "Install all" +UPDATE_QUESTION = "VitaShell %s is now available.\\Do you want to update the application?"