forked from Mirror/GodMode9
Implemented new file selector
This commit is contained in:
parent
d50e6b88ae
commit
732165153b
@ -44,6 +44,7 @@
|
|||||||
#define COLOR_FILE COLOR_TINTEDGREEN
|
#define COLOR_FILE COLOR_TINTEDGREEN
|
||||||
#define COLOR_DIR COLOR_TINTEDBLUE
|
#define COLOR_DIR COLOR_TINTEDBLUE
|
||||||
#define COLOR_ROOT COLOR_GREY
|
#define COLOR_ROOT COLOR_GREY
|
||||||
|
#define COLOR_ENTRY(e) (((e)->marked) ? COLOR_MARKED : ((e)->type == T_DIR) ? COLOR_DIR : ((e)->type == T_FILE) ? COLOR_FILE : ((e)->type == T_ROOT) ? COLOR_ROOT : COLOR_GREY)
|
||||||
|
|
||||||
// hex viewer colors
|
// hex viewer colors
|
||||||
#define COLOR_HVOFFS RGB(0x40, 0x60, 0x50)
|
#define COLOR_HVOFFS RGB(0x40, 0x60, 0x50)
|
||||||
|
@ -598,6 +598,96 @@ u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) {
|
|||||||
return (sel >= n) ? 0 : sel + 1;
|
return (sel >= n) ? 0 : sel + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ShowFileScrollPrompt(u32 n, const DirEntry** options, bool hide_ext, const char *format, ...) {
|
||||||
|
u32 str_height, fname_len;
|
||||||
|
u32 x, y, yopt;
|
||||||
|
const u32 item_width = SCREEN_WIDTH(MAIN_SCREEN) - 40;
|
||||||
|
int sel = 0, scroll = 0;
|
||||||
|
u32 n_show = min(n, 10);
|
||||||
|
|
||||||
|
char str[STRBUF_SIZE] = { 0 };
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
vsnprintf(str, STRBUF_SIZE, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (n == 0) return 0; // check for low number of options
|
||||||
|
// else if (n == 1) return ShowPrompt(true, "%s\n%s?", str, options[0]) ? 1 : 0;
|
||||||
|
|
||||||
|
str_height = GetDrawStringHeight(str) + (n_show * (line_height + 2)) + (4 * line_height);
|
||||||
|
x = (SCREEN_WIDTH_MAIN - item_width) / 2;
|
||||||
|
y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2;
|
||||||
|
yopt = y + GetDrawStringHeight(str) + 8;
|
||||||
|
fname_len = min(64, item_width / FONT_WIDTH_EXT - 14);
|
||||||
|
|
||||||
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
|
DrawStringF(MAIN_SCREEN, x, y, COLOR_STD_FONT, COLOR_STD_BG, "%s", str);
|
||||||
|
DrawStringF(MAIN_SCREEN, x, yopt + (n_show*(line_height+2)) + line_height, COLOR_STD_FONT, COLOR_STD_BG, "(<A> select, <B> cancel)");
|
||||||
|
while (true) {
|
||||||
|
for (u32 i = scroll; i < scroll+n_show; i++) {
|
||||||
|
char bytestr[16];
|
||||||
|
FormatBytes(bytestr, options[i]->size);
|
||||||
|
|
||||||
|
char content_str[64 + 1];
|
||||||
|
char temp_str[256];
|
||||||
|
strncpy(temp_str, options[i]->name, 255);
|
||||||
|
|
||||||
|
char* dot = strrchr(temp_str, '.');
|
||||||
|
if (hide_ext && dot) *dot = '\0';
|
||||||
|
|
||||||
|
ResizeString(content_str, temp_str, fname_len, 8, false);
|
||||||
|
|
||||||
|
DrawStringF(MAIN_SCREEN, x, yopt + ((line_height+2)*(i-scroll)),
|
||||||
|
(sel == (int)i) ? COLOR_STD_FONT : COLOR_ENTRY(options[i]), COLOR_STD_BG, "%2.2s %s",
|
||||||
|
(sel == (int)i) ? "->" : "", content_str);
|
||||||
|
|
||||||
|
DrawStringF(MAIN_SCREEN, x + item_width - font_width * 11, yopt + ((line_height+2)*(i-scroll)),
|
||||||
|
(sel == (int)i) ? COLOR_STD_FONT : COLOR_ENTRY(options[i]), COLOR_STD_BG, "%10.10s",
|
||||||
|
(options[i]->type == T_DIR) ? "(dir)" : (options[i]->type == T_DOTDOT) ? "(..)" : bytestr);
|
||||||
|
}
|
||||||
|
// show [n more]
|
||||||
|
if (n - n_show - scroll) {
|
||||||
|
char more_str[64 + 1];
|
||||||
|
snprintf(more_str, 64, " [%d more]", (int)(n - (n_show-1) - scroll));
|
||||||
|
DrawStringF(MAIN_SCREEN, x, yopt + (line_height+2)*(n_show-1), COLOR_LIGHTGREY, COLOR_STD_BG, "%-*s", item_width / font_width, more_str);
|
||||||
|
}
|
||||||
|
// show scroll bar
|
||||||
|
u32 bar_x = x + item_width + 2;
|
||||||
|
const u32 flist_height = (n_show * (line_height + 2));
|
||||||
|
const u32 bar_width = 2;
|
||||||
|
if (n > n_show) { // draw position bar at the right
|
||||||
|
const u32 bar_height_min = 32;
|
||||||
|
u32 bar_height = (n_show * flist_height) / n;
|
||||||
|
if (bar_height < bar_height_min) bar_height = bar_height_min;
|
||||||
|
const u32 bar_y = ((u64) scroll * (flist_height - bar_height)) / (n - n_show) + yopt;
|
||||||
|
|
||||||
|
DrawRectangle(MAIN_SCREEN, bar_x, yopt, bar_width, (bar_y - yopt), COLOR_STD_BG);
|
||||||
|
DrawRectangle(MAIN_SCREEN, bar_x, bar_y + bar_height, bar_width, SCREEN_HEIGHT - (bar_y + bar_height), COLOR_STD_BG);
|
||||||
|
DrawRectangle(MAIN_SCREEN, bar_x, bar_y, bar_width, bar_height, COLOR_SIDE_BAR);
|
||||||
|
} else DrawRectangle(MAIN_SCREEN, bar_x, yopt, bar_width, flist_height, COLOR_STD_BG);
|
||||||
|
|
||||||
|
u32 pad_state = InputWait(0);
|
||||||
|
if (pad_state & BUTTON_DOWN) sel++;
|
||||||
|
else if (pad_state & BUTTON_UP) sel--;
|
||||||
|
else if (pad_state & BUTTON_RIGHT) sel += n_show;
|
||||||
|
else if (pad_state & BUTTON_LEFT) sel -= n_show;
|
||||||
|
else if (pad_state & BUTTON_A) break;
|
||||||
|
else if (pad_state & BUTTON_B) {
|
||||||
|
sel = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sel < 0) sel = 0;
|
||||||
|
else if (sel >= (int)n) sel = n-1;
|
||||||
|
if (sel < scroll) scroll = sel;
|
||||||
|
else if (sel == (int) n-1 && sel >= (int)(scroll + n_show - 1)) scroll = sel - n_show + 1;
|
||||||
|
else if (sel >= (int)(scroll + (n_show-1) - 1)) scroll = sel - (n_show-1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
|
|
||||||
|
return (sel >= (int)n) ? 0 : sel + 1;
|
||||||
|
}
|
||||||
|
|
||||||
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...) {
|
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...) {
|
||||||
char str[STRBUF_SIZE] = { 0 };
|
char str[STRBUF_SIZE] = { 0 };
|
||||||
char* ptr = str;
|
char* ptr = str;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <vram.h>
|
#include <vram.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "colors.h"
|
#include "colors.h"
|
||||||
|
#include "fsdir.h" // only required for ShowFileScrollPrompt
|
||||||
|
|
||||||
|
|
||||||
#define BYTES_PER_PIXEL 3
|
#define BYTES_PER_PIXEL 3
|
||||||
@ -73,6 +74,7 @@ void ShowString(const char *format, ...);
|
|||||||
void ShowIconString(u8* icon, int w, int h, const char *format, ...);
|
void ShowIconString(u8* icon, int w, int h, const char *format, ...);
|
||||||
bool ShowPrompt(bool ask, const char *format, ...);
|
bool ShowPrompt(bool ask, const char *format, ...);
|
||||||
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
||||||
|
u32 ShowFileScrollPrompt(u32 n, const DirEntry** entries, bool hide_ext, const char *format, ...);
|
||||||
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...);
|
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...);
|
||||||
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...);
|
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...);
|
||||||
u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);
|
u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);
|
||||||
|
@ -794,7 +794,7 @@ bool PathAttr(const char* path, u8 attr, u8 mask) {
|
|||||||
return (f_chmod(path, attr, mask) == FR_OK);
|
return (f_chmod(path, attr, mask) == FR_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileSelectorWorker(char* result, const char* text, const char* path, const char* pattern, u32 flags, void* buffer) {
|
bool FileSelectorWorker(char* result, const char* text, const char* path, const char* pattern, u32 flags, void* buffer, bool new_style) {
|
||||||
DirStruct* contents = (DirStruct*) buffer;
|
DirStruct* contents = (DirStruct*) buffer;
|
||||||
char path_local[256];
|
char path_local[256];
|
||||||
strncpy(path_local, path, 256);
|
strncpy(path_local, path, 256);
|
||||||
@ -813,7 +813,7 @@ bool FileSelectorWorker(char* result, const char* text, const char* path, const
|
|||||||
|
|
||||||
while (pos < contents->n_entries) {
|
while (pos < contents->n_entries) {
|
||||||
char opt_names[_MAX_FS_OPT+1][32+1];
|
char opt_names[_MAX_FS_OPT+1][32+1];
|
||||||
DirEntry* res_entry[_MAX_FS_OPT+1] = { NULL };
|
DirEntry* res_entry[MAX_DIR_ENTRIES+1] = { NULL };
|
||||||
u32 n_opt = 0;
|
u32 n_opt = 0;
|
||||||
for (; pos < contents->n_entries; pos++) {
|
for (; pos < contents->n_entries; pos++) {
|
||||||
DirEntry* entry = &(contents->entry[pos]);
|
DirEntry* entry = &(contents->entry[pos]);
|
||||||
@ -821,35 +821,38 @@ bool FileSelectorWorker(char* result, const char* text, const char* path, const
|
|||||||
((entry->type == T_FILE) && (no_files || (fvx_match_name(entry->name, pattern) != FR_OK))) ||
|
((entry->type == T_FILE) && (no_files || (fvx_match_name(entry->name, pattern) != FR_OK))) ||
|
||||||
(entry->type == T_DOTDOT) || (strncmp(entry->name, "._", 2) == 0))
|
(entry->type == T_DOTDOT) || (strncmp(entry->name, "._", 2) == 0))
|
||||||
continue;
|
continue;
|
||||||
if (n_opt == _MAX_FS_OPT) {
|
if (!new_style && n_opt == _MAX_FS_OPT) {
|
||||||
snprintf(opt_names[n_opt++], 32, "[more...]");
|
snprintf(opt_names[n_opt++], 32, "[more...]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char temp_str[256];
|
if (!new_style) {
|
||||||
snprintf(temp_str, 256, "%s", entry->name);
|
char temp_str[256];
|
||||||
if (hide_ext && (entry->type == T_FILE)) {
|
snprintf(temp_str, 256, "%s", entry->name);
|
||||||
char* dot = strrchr(temp_str, '.');
|
if (hide_ext && (entry->type == T_FILE)) {
|
||||||
if (dot) *dot = '\0';
|
char* dot = strrchr(temp_str, '.');
|
||||||
|
if (dot) *dot = '\0';
|
||||||
|
}
|
||||||
|
TruncateString(opt_names[n_opt], temp_str, 32, 8);
|
||||||
}
|
}
|
||||||
TruncateString(opt_names[n_opt], temp_str, 32, 8);
|
|
||||||
res_entry[n_opt++] = entry;
|
res_entry[n_opt++] = entry;
|
||||||
n_found++;
|
n_found++;
|
||||||
}
|
}
|
||||||
if ((pos >= contents->n_entries) && (n_opt < n_found))
|
if ((pos >= contents->n_entries) && (n_opt < n_found) && !new_style)
|
||||||
snprintf(opt_names[n_opt++], 32, "[more...]");
|
snprintf(opt_names[n_opt++], 32, "[more...]");
|
||||||
if (!n_opt) break;
|
if (!n_opt) break;
|
||||||
|
|
||||||
const char* optionstr[_MAX_FS_OPT+1] = { NULL };
|
const char* optionstr[_MAX_FS_OPT+1] = { NULL };
|
||||||
for (u32 i = 0; i <= _MAX_FS_OPT; i++) optionstr[i] = opt_names[i];
|
for (u32 i = 0; i <= _MAX_FS_OPT; i++) optionstr[i] = opt_names[i];
|
||||||
u32 user_select = ShowSelectPrompt(n_opt, optionstr, "%s", text);
|
u32 user_select = new_style ? ShowFileScrollPrompt(n_opt, (const DirEntry**)res_entry, hide_ext, "%s", text)
|
||||||
|
: ShowSelectPrompt(n_opt, optionstr, "%s", text);
|
||||||
if (!user_select) return false;
|
if (!user_select) return false;
|
||||||
DirEntry* res_local = res_entry[user_select-1];
|
DirEntry* res_local = res_entry[user_select-1];
|
||||||
if (res_local && (res_local->type == T_DIR)) { // selected dir
|
if (res_local && (res_local->type == T_DIR)) { // selected dir
|
||||||
if (select_dirs) {
|
if (select_dirs) {
|
||||||
strncpy(result, res_local->path, 256);
|
strncpy(result, res_local->path, 256);
|
||||||
return true;
|
return true;
|
||||||
} else if (FileSelectorWorker(result, text, res_local->path, pattern, flags, buffer)) {
|
} else if (FileSelectorWorker(result, text, res_local->path, pattern, flags, buffer, new_style)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -867,11 +870,11 @@ bool FileSelectorWorker(char* result, const char* text, const char* path, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags) {
|
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags, bool new_style) {
|
||||||
void* buffer = (void*) malloc(sizeof(DirStruct));
|
void* buffer = (void*) malloc(sizeof(DirStruct));
|
||||||
if (!buffer) return false;
|
if (!buffer) return false;
|
||||||
|
|
||||||
bool ret = FileSelectorWorker(result, text, path, pattern, flags, buffer);
|
bool ret = FileSelectorWorker(result, text, path, pattern, flags, buffer, new_style);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -85,4 +85,4 @@ bool PathRename(const char* path, const char* newname);
|
|||||||
bool PathAttr(const char* path, u8 attr, u8 mask);
|
bool PathAttr(const char* path, u8 attr, u8 mask);
|
||||||
|
|
||||||
/** Select a file **/
|
/** Select a file **/
|
||||||
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags);
|
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags, bool new_style);
|
||||||
|
@ -116,5 +116,5 @@ bool FileSelectorSupport(char* result, const char* text, const char* dname, cons
|
|||||||
{
|
{
|
||||||
char path[256];
|
char path[256];
|
||||||
if (!GetSupportDir(path, dname)) return false;
|
if (!GetSupportDir(path, dname)) return false;
|
||||||
return FileSelector(result, text, path, pattern, HIDE_EXT);
|
return FileSelector(result, text, path, pattern, HIDE_EXT, false);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#define COLOR_TOP_BAR (PERM_RED ? COLOR_RED : PERM_ORANGE ? COLOR_ORANGE : PERM_BLUE ? COLOR_BRIGHTBLUE : \
|
#define COLOR_TOP_BAR (PERM_RED ? COLOR_RED : PERM_ORANGE ? COLOR_ORANGE : PERM_BLUE ? COLOR_BRIGHTBLUE : \
|
||||||
PERM_YELLOW ? COLOR_BRIGHTYELLOW : PERM_GREEN ? COLOR_GREEN : COLOR_WHITE)
|
PERM_YELLOW ? COLOR_BRIGHTYELLOW : PERM_GREEN ? COLOR_GREEN : COLOR_WHITE)
|
||||||
#define COLOR_ENTRY(e) (((e)->marked) ? COLOR_MARKED : ((e)->type == T_DIR) ? COLOR_DIR : ((e)->type == T_FILE) ? COLOR_FILE : ((e)->type == T_ROOT) ? COLOR_ROOT : COLOR_GREY)
|
|
||||||
|
|
||||||
#define BOOTPAUSE_KEY (BUTTON_R1|BUTTON_UP)
|
#define BOOTPAUSE_KEY (BUTTON_R1|BUTTON_UP)
|
||||||
#define BOOTMENU_KEY (BUTTON_R1|BUTTON_LEFT)
|
#define BOOTMENU_KEY (BUTTON_R1|BUTTON_LEFT)
|
||||||
|
@ -153,8 +153,8 @@ Gm9ScriptCmd cmd_list[] = {
|
|||||||
{ CMD_ID_QR , "qr" , 2, 0 },
|
{ CMD_ID_QR , "qr" , 2, 0 },
|
||||||
{ CMD_ID_ASK , "ask" , 1, 0 },
|
{ CMD_ID_ASK , "ask" , 1, 0 },
|
||||||
{ CMD_ID_INPUT , "input" , 2, 0 },
|
{ CMD_ID_INPUT , "input" , 2, 0 },
|
||||||
{ CMD_ID_FILESEL , "filesel" , 3, _FLG('d') },
|
{ CMD_ID_FILESEL , "filesel" , 3, _FLG('d') | _FLG('x') },
|
||||||
{ CMD_ID_DIRSEL , "dirsel" , 3, 0 },
|
{ CMD_ID_DIRSEL , "dirsel" , 3, _FLG('x') },
|
||||||
{ CMD_ID_SET , "set" , 2, 0 },
|
{ CMD_ID_SET , "set" , 2, 0 },
|
||||||
{ CMD_ID_STRSPLIT, "strsplit", 3, _FLG('b') | _FLG('f')},
|
{ CMD_ID_STRSPLIT, "strsplit", 3, _FLG('b') | _FLG('f')},
|
||||||
{ CMD_ID_STRREP , "strrep" , 3, 0 },
|
{ CMD_ID_STRREP , "strrep" , 3, 0 },
|
||||||
@ -562,6 +562,7 @@ u32 get_flag(char* str, u32 len, char* err_str) {
|
|||||||
else if (strncmp(str, "--silent", len) == 0) flag_char = 's';
|
else if (strncmp(str, "--silent", len) == 0) flag_char = 's';
|
||||||
else if (strncmp(str, "--unequal", len) == 0) flag_char = 'u';
|
else if (strncmp(str, "--unequal", len) == 0) flag_char = 'u';
|
||||||
else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w';
|
else if (strncmp(str, "--overwrite", len) == 0) flag_char = 'w';
|
||||||
|
else if (strncmp(str, "--explorer", len) == 0) flag_char = 'x';
|
||||||
|
|
||||||
if ((flag_char < 'a') && (flag_char > 'z')) {
|
if ((flag_char < 'a') && (flag_char > 'z')) {
|
||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "illegal flag");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "illegal flag");
|
||||||
@ -1039,11 +1040,11 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
} else {
|
} else {
|
||||||
u32 flags_ext = (flags & _FLG('d')) ? 0 : NO_DIRS;
|
u32 flags_ext = (flags & _FLG('d')) ? 0 : NO_DIRS;
|
||||||
*(npattern++) = '\0';
|
*(npattern++) = '\0';
|
||||||
ret = FileSelector(choice, argv[0], path, npattern, flags_ext);
|
ret = FileSelector(choice, argv[0], path, npattern, flags_ext, (flags & _FLG('x')));
|
||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fileselect abort");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "fileselect abort");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = FileSelector(choice, argv[0], path, NULL, NO_FILES | SELECT_DIRS);
|
ret = FileSelector(choice, argv[0], path, NULL, NO_FILES | SELECT_DIRS, (flags & _FLG('x')));
|
||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "dirselect abort");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "dirselect abort");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,11 +107,13 @@ echo $[TESTREP]
|
|||||||
# The 'filesel' command allows the user to choose a file inside a directory
|
# The 'filesel' command allows the user to choose a file inside a directory
|
||||||
# The path is stored inside a variable, and the selection can be limited via wildcards
|
# The path is stored inside a variable, and the selection can be limited via wildcards
|
||||||
# -d / --include_dirs allows to browse folders and select files inside
|
# -d / --include_dirs allows to browse folders and select files inside
|
||||||
|
# -x / --explorer uses new style file selector like main file explorer
|
||||||
filesel "Please select a file" 0:/*.* SELFILE
|
filesel "Please select a file" 0:/*.* SELFILE
|
||||||
|
|
||||||
# 'dirsel' COMMAND
|
# 'dirsel' COMMAND
|
||||||
# The 'dirsel' command works identically to the 'filesel' command, but allows selecting a dir
|
# The 'dirsel' command works identically to the 'filesel' command, but allows selecting a dir
|
||||||
# Note that a final slash ('/') is not expected here and there can be no wildcard pattern.
|
# Note that a final slash ('/') is not expected here and there can be no wildcard pattern.
|
||||||
|
# -x / --explorer uses new style file selector like main file explorer
|
||||||
dirsel "Now, select a dir" 0: SELDIR
|
dirsel "Now, select a dir" 0: SELDIR
|
||||||
echo "You selected $[SELFILE]\nand $[SELDIR]\nWe'll do nothing with either :)."
|
echo "You selected $[SELFILE]\nand $[SELDIR]\nWe'll do nothing with either :)."
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user