void string_base::fix_dir_separator(char c) { #ifdef _WIN32 end_with(c); #else end_with_slash(); #endif }
void CdllsDlg::OnBnClickedSave() { TCHAR app_path_buf[PATH_LEN]; memset(app_path_buf,0,sizeof(app_path_buf)); GetModuleFileName(NULL, app_path_buf,sizeof(app_path_buf)/sizeof(app_path_buf[0])); int pathlen = _tcslen(app_path_buf); int i = pathlen-1; while(i>0) { if(app_path_buf[i]==_T('\\') ) { app_path_buf[i+1] = 0; break; } i--; } TCHAR szFilters[] =_T("Text Files (*.txt)\0*.txt\0") _T("All Files (*.*)\0*.*\0"); CFileDialog fdlg (FALSE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST |OFN_EXPLORER, szFilters, AfxGetMainWnd()); //CFileDialog ofdlg(FALSE); fdlg.m_ofn.lpstrFilter = szFilters; //CFileDialog fdlg(FALSE,_T(".txt"),_T("dlllist.txt")); fdlg.m_ofn.lpstrInitialDir =app_path_buf; if(IDOK!=fdlg.DoModal()) return; std::basic_string<TCHAR> savepathname = fdlg.m_ofn.lpstrFile; if(1==fdlg.m_ofn.nFilterIndex && !end_with(savepathname,_T(".txt"),true) ) { savepathname += _T(".txt"); } std::basic_fstream<TCHAR> ofile; ofile.open( (LPCSTR)_bstr_t(savepathname.c_str()),std::ios_base::out|std::ios_base::trunc); HWND hwndListView =GetDlgItem(IDC_LVW)->m_hWnd; int rows = 0; rows = ListView_GetItemCount(hwndListView); int cols = 0; HWND headerwnd = ListView_GetHeader(hwndListView); cols = Header_GetItemCount(headerwnd); for(int i=0;i<rows;i++) { for(int j=0;j<cols;j++) { app_path_buf[0] = 0; ListView_GetItemText(hwndListView,i,j,app_path_buf,ARRAY_SIZE(app_path_buf)); if(j<cols-1) ofile<<app_path_buf<<_T(" "); else { ofile<<app_path_buf<<(char)0xd<<(char)0xa; } } } ofile.close(); }
void get_dir(const char *path) { DIR *fd; struct dirent *file; char new_path[512]; strncpy(new_path, path, 512); if (NULL == (fd = opendir(new_path))) { printf("\xb[3;1HDirectory empty..."); return; } memset(picker, 0, sizeof(picker_s)); strncpy(picker->now_path, new_path, 512); while ((file = readdir(fd))) { if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, "..")) continue; if (file->d_type != DT_DIR) { const char *ext = get_filename_ext(file->d_name); if (strcasecmp(ext, "bin") != 0 && strcasecmp(ext, "dat") != 0 && strcasecmp(ext, "3dsx") != 0) continue; } // file name strncpy(picker->files[picker->file_count].name, file->d_name, 512); // build absolute path if (end_with(new_path, '/')) { snprintf(picker->files[picker->file_count].path, 512, "%s%s", new_path, file->d_name); } else { snprintf(picker->files[picker->file_count].path, 512, "%s/%s", new_path, file->d_name); } // dir vs file if (file->d_type != DT_DIR) { picker->files[picker->file_count].isDir = false; // file size struct stat st; stat(picker->files[picker->file_count].path, &st); picker->files[picker->file_count].size = (u64) st.st_size; } else { picker->files[picker->file_count].isDir = true; } picker->file_count++; } if (picker->file_count > 1) { qsort(picker->files, (size_t) picker->file_count, sizeof(*picker->files), alphasort); } closedir(fd); }
void string_base::end_with_slash() { end_with( io::path::getDefaultSeparator() ); }
int main (int argc, char **argv) { // Optimize allocation for Tornado (2GB hash allocated after 1GB dictionary) AllocTopDown = FALSE; // Operation mode OPMODE global_mode=AUTO; // Record that stores all the info required for ReadWriteCallback static Results r; r.use_cpu_time = r.quiet_title = r.quiet_header = r.quiet_progress = r.quiet_result = FALSE; // Default compression parameters are equivalent to option -5 r.method = std_Tornado_method [default_Tornado_method]; // Delete successfully (de)compressed input files bool delete_input_files = FALSE; // Count of files to process int fcount=0; // Output path/filename const char *output_filename = NULL; // Process options until "--" // 1. First, process -1..-16 option if any for (char **argv_ptr = argv; *++argv_ptr!=NULL; ) { char *param = *argv_ptr; if (*param == '-') { param++; if (strcasecmp(param,"-")==0) break; // "--" is a "stop processing" option else if (isdigit(*param)) r.method = std_Tornado_method[check_parse_int (param, 1, elements(std_Tornado_method)-1, param-1)]; } } // 2. Second, process rest of options for (char **argv_ptr = argv; *++argv_ptr!=NULL; ) { char *param = *argv_ptr; if (param[0] != '-' || param[1]=='\0') { fcount++; } else { param++; int error=0; if (strcasecmp(param,"-")==0) break; else if (strcasecmp(param,"") ==0) continue; else if (strcasecmp(param,"z")==0) global_mode=_COMPRESS; else if (strcasecmp(param,"d")==0) global_mode=_DECOMPRESS; else if (strcasecmp(param,"delete")==0) delete_input_files=TRUE; else if (strcasecmp(param,"t")==0) output_filename=""; else if (strcasecmp(param,"q")==0) r.quiet_title = r.quiet_header = r.quiet_progress = r.quiet_result = TRUE; #ifndef FREEARC_NO_TIMING else if (strcasecmp(param,"cpu")==0) r.use_cpu_time=TRUE; #endif else if (strcasecmp(param,"h")==0) global_mode=HELP; else if (strcasecmp(param,"b")==0) r.method.buffer = MAX_BUFFER_SIZE; // set buffer size to the maximum supported by LZ coders else if (strcasecmp(param,"x")==0) r.method.caching_finder = CACHING_MF4; else if (strcasecmp(param,"xx")==0) r.method.caching_finder = CYCLED_MF4; else if (strcasecmp(param,"x+")==0) r.method.caching_finder = CACHING_MF4; else if (strcasecmp(param,"x-")==0) r.method.caching_finder = NON_CACHING_MF; else if (strcasecmp(param,"t+")==0) r.method.find_tables = TRUE; else if (strcasecmp(param,"t-")==0) r.method.find_tables = FALSE; else if (strcasecmp(param,"t1")==0) r.method.find_tables = TRUE; else if (strcasecmp(param,"t0")==0) r.method.find_tables = FALSE; else if (strcasecmp(param,"s")==0) r.method.hash3 = 1; else if (strcasecmp(param,"ss")==0) r.method.hash3 = 2; else if (strcasecmp(param,"s+")==0) r.method.hash3 = 1; else if (strcasecmp(param,"s-")==0) r.method.hash3 = 0; else if (start_with(param,"fb")) r.method.fast_bytes = check_parse_int (param+2, MIN_FAST_BYTES, MAX_FAST_BYTES, *argv_ptr); #ifdef FREEARC_WIN else if (strcasecmp(param,"slp-")==0) DefaultLargePageMode = DISABLE; else if (strcasecmp(param,"slp" )==0) DefaultLargePageMode = TRY; else if (strcasecmp(param,"slp+")==0) DefaultLargePageMode = FORCE; #endif else if (start_with(param,"rem")) /* ignore option */; else if (isdigit(*param)) ; // -1..-16 option is already processed :) else switch( tolower(*param++) ) { case 'b': r.method.buffer = check_parse_mem (param, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE, *argv_ptr); break; case 'h': r.method.hashsize = check_parse_mem (param, MIN_HASH_SIZE, MAX_HASH_SIZE, *argv_ptr); break; case 'l': r.method.hash_row_width = check_parse_int (param, 1, MAX_HASH_ROW_WIDTH, *argv_ptr); break; case 'u': r.method.update_step = check_parse_int (param, 1, MAX_UPDATE_STEP, *argv_ptr); break; case 'c': r.method.encoding_method = check_parse_int (param, BYTECODER, ARICODER, *argv_ptr); break; case 's': r.method.hash3 = check_parse_int (param, 0, 2, *argv_ptr); break; case 'p': r.method.match_parser = parseInt (param, &error); break; case 'x': r.method.caching_finder = parseInt (param, &error); break; case 'o': output_filename = param; break; case 'q': #ifndef FREEARC_NO_TIMING r.quiet_title = strchr (param, 't'); r.quiet_progress = strchr (param, 'p'); #endif r.quiet_header = strchr (param, 'h'); r.quiet_result = strchr (param, 'r'); break; case 'a': switch( tolower(*param++) ) { case 'h': r.method.auxhash_size = check_parse_mem (param, MIN_HASH_SIZE, MAX_HASH_SIZE, *argv_ptr); goto check_for_errors; case 'l': r.method.auxhash_row_width = check_parse_int (param, 1, MAX_HASH_ROW_WIDTH, *argv_ptr); goto check_for_errors; } // 'a' should be the last case! default : fprintf (stderr, "ERROR: unknown option '%s'\n", *argv_ptr); exit(FREEARC_EXIT_ERROR); } check_for_errors: if (error) { fprintf (stderr, "ERROR: bad option format: '%s'\n", *argv_ptr); exit(FREEARC_EXIT_ERROR); } if (!(r.method.match_parser==GREEDY || r.method.match_parser==LAZY || r.method.match_parser==OPTIMAL)) { fprintf (stderr, "ERROR: bad option value: '%s'\n", *argv_ptr); exit(FREEARC_EXIT_ERROR); } int mf = r.method.caching_finder; r.method.caching_finder = mf = (mf==CACHING_MF4_DUB? CACHING_MF4 : (mf==CYCLED_MF4_DUB? CYCLED_MF4 : mf)); if (!(mf==NON_CACHING_MF || (CYCLED_MF4<=mf && mf<=CYCLED_MF7) || (CACHING_MF4<=mf && mf<=CACHING_MF7) || (BT_MF4<=mf && mf<=BT_MF7))) { fprintf (stderr, "ERROR: non-existing match finder: '%s'\n", *argv_ptr); exit(FREEARC_EXIT_ERROR); } } } // No files to compress: read from stdin and write to stdout if (global_mode!=HELP && fcount==0 && (global_mode!=AUTO || !isatty(0) && !isatty(1)) ) { static char *_argv[] = {argv[0], (char*)"-", NULL}; argv = _argv; fcount = 1; } else if (global_mode==HELP || fcount==0) { char h[100], ah[100], b[100], MinHashSizeStr[100], MaxHashSizeStr[100], MinBufSizeStr[100], MaxBufSizeStr[100]; showMem64 (r.method.hashsize, h); showMem64 (r.method.auxhash_size, ah); showMem64 (r.method.buffer, b); showMem64 (MIN_HASH_SIZE, MinHashSizeStr); showMem64 (MAX_HASH_SIZE+1, MaxHashSizeStr); showMem64 (MIN_BUFFER_SIZE, MinBufSizeStr); showMem64 (MAX_BUFFER_SIZE, MaxBufSizeStr); printf( "Tornado compressor v0.6 (c) [email protected] http://freearc.org 2014-03-08\n" "\n" " Usage: tor [options and files in any order]\n" " -# -- compression level (1..%d), default %d\n", int(elements(std_Tornado_method))-1, default_Tornado_method); printf( " -z -- force compression\n" " -d -- force decompression\n" " -oNAME -- output filename/directory (default %s/%s)\n", COMPRESS_EXT, DECOMPRESS_EXT); printf( " -t -- test (de)compression (redirect output to nul)\n" " -delete -- delete successfully (de)compressed input files\n" #ifdef FREEARC_NO_TIMING " -q -- be quiet; -q[hr]* disables header/results individually\n" #else " -q -- be quiet; -q[thpr]* disables title/header/progress/results individually\n" " -cpu -- compute raw CPU time (for benchmarking)\n" #endif #ifdef FREEARC_WIN " -slp[+/-/] -- force/disable/try(default) large pages support (2mb/4mb)\n" #endif " -rem... -- command-line remark\n" " -h -- display this help\n" " -- -- stop flags processing\n" " \"-\" used as filename means stdin/stdout\n" "\n" " Advanced compression parameters:\n" " -b# -- buffer size (%s..%s), default %s\n", MinBufSizeStr, MaxBufSizeStr, b); printf( " -h# -- hash size (%s..%s-1), default %s\n", MinHashSizeStr, MaxHashSizeStr, h); printf( " -l# -- length of hash row (1..%d), default %d\n", int(MAX_HASH_ROW_WIDTH), r.method.hash_row_width); printf( " -ah# -- auxiliary hash size (%s..%s-1), default %s\n", MinHashSizeStr, MaxHashSizeStr, ah); printf( " -al# -- auxiliary hash row length (1..%d), default %d\n", int(MAX_HASH_ROW_WIDTH), r.method.auxhash_row_width); printf( " -u# -- update step (1..%d), default %d\n", int(MAX_UPDATE_STEP), r.method.update_step); printf( " -c# -- coder (1-bytes, 2-bits, 3-huf, 4-arith), default %d\n", r.method.encoding_method); printf( " -p# -- parser (1-greedy, 2-lazy, 4-optimal), default %d\n", r.method.match_parser); printf( " -x# -- match finder (0: non-caching ht4, 4-7: cycling cached ht4..ht7,\n" " 14-17: shifting cached ht4..ht7, 24-27: bt4..bt7), default %d\n", r.method.caching_finder); printf( " -s# -- 2/3-byte hash (0-disabled, 1-fast, 2-max), default %d\n", r.method.hash3); printf( " -t# -- table diffing (0-disabled, 1-enabled), default %d\n", r.method.find_tables); printf( " -fb# -- fast bytes in the optimal parser (%d..%d), default %d\n", int(MIN_FAST_BYTES), int(MAX_FAST_BYTES), r.method.fast_bytes); printf( "\n" " Predefined methods:\n"); for (int i=1; i<elements(std_Tornado_method); i++) { printf(" %-8d-- %s\n", -i, name(std_Tornado_method[i])); } exit(EXIT_SUCCESS); } // (De)compress all files given on cmdline bool parse_options=TRUE; // options will be parsed until "--" Install_signal_handler(signal_handler); for (char **parameters = argv; *++parameters!=NULL; ) { // If options are still parsed and this argument starts with "-" - it's an option if (parse_options && parameters[0][0]=='-' && parameters[0][1]) { if (strequ(*parameters,"--")) parse_options=FALSE; continue; } // Save input filename r.filename = *parameters; // Select operation mode if it was not specified on cmdline r.mode = global_mode != AUTO? global_mode : end_with (r.filename, COMPRESS_EXT)? _DECOMPRESS : _COMPRESS; // Extension that should be added to output filenames const char *MODE_EXT = r.mode==_COMPRESS? COMPRESS_EXT : DECOMPRESS_EXT; // Construct output filename if (r.mode==BENCHMARK || output_filename && strequ (output_filename, "")) { // Redirect output to nul strcpy (r.outname, ""); } else if (output_filename) { if (strequ(output_filename,"-")) strcpy (r.outname, output_filename); else if (is_path_char (last_char (output_filename))) {sprintf(r.outname, "%s%s", output_filename, drop_dirname(r.filename)); goto add_remove_ext;} else if (dir_exists (output_filename)) {sprintf(r.outname, "%s%c%s", output_filename, PATH_DELIMITER, drop_dirname(r.filename)); goto add_remove_ext;} else strcpy (r.outname, output_filename); } else if (strequ(r.filename,"-")) { strcpy (r.outname, r.filename); } else { // No output filename was given on cmdline: // on compression - add COMPRESS_EXT // on decompression - remove COMPRESS_EXT (and add DECOMPRESS_EXT if file already exists) strcpy (r.outname, r.filename); add_remove_ext: // Remove COMPRESS_EXT on the end of name or add DECOMPRESS_EXT (unless we are in _COMPRESS mode) if (r.mode!=_COMPRESS && end_with (r.outname, COMPRESS_EXT)) { r.outname [strlen(r.outname) - strlen(COMPRESS_EXT)] = '\0'; if (file_exists (r.outname)) strcat(r.outname, MODE_EXT); } else { strcat(r.outname, MODE_EXT); } } // Open input file r.fin = strequ (r.filename, "-")? stdin : file_open_read_binary(r.filename); if (r.fin == NULL) { fprintf (stderr, "\n Can't open %s for read\n", r.filename); exit(FREEARC_EXIT_ERROR); } set_binary_mode (r.fin); // Open output file if (*r.outname) { r.fout = strequ (r.outname, "-")? stdout : file_open_write_binary(r.outname); if (r.fout == NULL) { fprintf (stderr, "\n Can't open %s for write\n", r.outname); exit(FREEARC_EXIT_ERROR); } set_binary_mode (r.fout); } else { r.fout = NULL; } // Prepare to (de)compression int result; char filesize_str[100]; start_print_stats(r); // Perform actual (de)compression switch (r.mode) { case _COMPRESS: { if (!r.quiet_header && r.filesize >= 0) fprintf (stderr, "Compressing %s bytes with %s\n", show3(r.filesize,filesize_str), name(r.method)); PackMethod m = r.method; if (r.filesize >= 0) m.buffer = mymin (m.buffer, r.filesize+LOOKAHEAD*2); result = tor_compress (m, ReadWriteCallback, &r, NULL, -1); break; } case _DECOMPRESS: { //if (!r.quiet_header && !strequ (r.outname, "-")) fprintf (stderr, "Unpacking %.3lf mb\n", double(r.filesize)/1000/1000); result = tor_decompress (ReadWriteCallback, &r, NULL, -1); break; } } // Finish (de)compression print_final_stats(r); fclose (r.fin); if (r.fout) fclose (r.fout); if (result == FREEARC_OK) { if (delete_input_files && !strequ(r.filename,"-")) delete_file(r.filename); } else { if (!strequ(r.outname,"-") && !strequ(r.outname,"")) delete_file(r.outname); switch (result) { case FREEARC_ERRCODE_INVALID_COMPRESSOR: fprintf (stderr, "\nThis compression mode isn't supported by small Tornado version, use full version instead!"); break; case FREEARC_ERRCODE_NOT_ENOUGH_MEMORY: fprintf (stderr, "\nNot enough memory for (de)compression!"); break; case FREEARC_ERRCODE_READ: fprintf (stderr, "\nRead error! Bad media?"); break; case FREEARC_ERRCODE_WRITE: fprintf (stderr, "\nWrite error! Disk full?"); break; case FREEARC_ERRCODE_BAD_COMPRESSED_DATA: fprintf (stderr, "\nData can't be decompressed!"); break; default: fprintf (stderr, "\n(De)compression failed with error code %d!", result); break; } exit(FREEARC_EXIT_ERROR); } // going to next file... } return EXIT_SUCCESS; }
void pick_file(file_s *picked, const char *path) { picker = malloc(sizeof(picker_s)); get_dir(path); // key repeat timer static time_t t_start = 0, t_end = 0, t_elapsed = 0; while (aptMainLoop()) { hidScanInput(); u32 kHeld = hidKeysHeld(); u32 kDown = hidKeysDown(); if (hidKeysUp()) { time(&t_start); // reset held timer } if (kDown & KEY_DOWN) { picker->file_index++; if (picker->file_index >= picker->file_count) picker->file_index = 0; time(&t_start); } else if (kHeld & KEY_DOWN) { time(&t_end); t_elapsed = t_end - t_start; if (t_elapsed > 0) { picker->file_index++; if (picker->file_index >= picker->file_count) picker->file_index = 0; svcSleep(100); } } if (kDown & KEY_UP) { picker->file_index--; if (picker->file_index < 0) picker->file_index = picker->file_count - 1; time(&t_start); } else if (kHeld & KEY_UP) { time(&t_end); t_elapsed = t_end - t_start; if (t_elapsed > 0) { picker->file_index--; if (picker->file_index < 0) picker->file_index = picker->file_count - 1; svcSleep(100); } } if (kDown & KEY_A) { int index = picker->file_index; if (!picker->files[index].isDir) { if (confirm(0, "Launch \"%s\" ?", picker->files[index].name)) { strncpy(picked->name, picker->files[index].name, 512); strncpy(picked->path, picker->files[index].path, 512); picked->isDir = picker->files[index].isDir; picked->size = picker->files[index].size; break; } } else { get_dir(picker->files[index].path); } } else if (kDown & KEY_X) { int index = picker->file_index; if (!picker->files[index].isDir) { const char *ext = get_filename_ext(picker->files[index].name); if (strcasecmp(ext, "3dsx") == 0) { if (confirm(3, "Add entry to boot menu: \"%s\" ?", picker->files[index].name)) { if (config->count > CONFIG_MAX_ENTRIES - 1) { debug("Maximum entries reached (%i)\n", CONFIG_MAX_ENTRIES); } else if (configAddEntry(picker->files[index].name, picker->files[index].path, 0) == 0) { debug("Added entry: %s\n", picker->files[index].name); } else { debug("Error adding entry: %s\n", picker->files[index].name); } } } } } else if (kDown & KEY_B) { // exit if we can't go back if (strlen(picker->now_path) <= 1) break; // remove slash if needed if (end_with(picker->now_path, '/')) picker->now_path[strlen(picker->now_path) - 1] = '\0'; // build path char *slash = strrchr(picker->now_path, '/'); if (slash == NULL) break; int len = (int) (slash - picker->now_path); picker->now_path[len] = '\0'; // enter new dir get_dir(picker->now_path); } gfxClear(); gfxDrawText(GFX_TOP, GFX_LEFT, &fontTitle, "*** Select a file ***", 130, 20); int minX = 16; int maxX = 400 - 16; int minY = 32; int maxY = 240 - 16; drawRect(GFX_TOP, GFX_LEFT, minX, minY, maxX, maxY, (u8) 0xFF, (u8) 0xFF, (u8) 0xFF); minY += 20; int i, y = 0; int page = picker->file_index / MAX_LINE; for (i = page * MAX_LINE; i < page * MAX_LINE + MAX_LINE; i++) { if (i >= picker->file_count) break; if (i == picker->file_index) { gfxDrawRectangle(GFX_TOP, GFX_LEFT, (u8[]) {0xDC, 0xDC, 0xDC}, minX + 4, minY + 16 * y, maxX - 23, 15); gfxDrawTextN(GFX_TOP, GFX_LEFT, &fontSelected, picker->files[i].name, 47, minX + 6, minY + 16 * y); if (!picker->files[i].isDir) { gfxDrawText(GFX_BOTTOM, GFX_LEFT, &fontTitle, "Informations", minX + 6, 20); gfxDrawText(GFX_BOTTOM, GFX_LEFT, &fontDefault, "Press (A) to launch\nPress (X) to add to boot menu", minX + 12, 40); } } else { gfxDrawTextN(GFX_TOP, GFX_LEFT, &fontDefault, picker->files[i].name, 47, minX + 6, minY + 16 * y); } y++; }
void pick_file(file_s *picked, const char *path) { picker = malloc(sizeof(picker_s)); get_dir(path); // key repeat timer static time_t t_start = 0, t_end = 0, t_elapsed = 0; while (aptMainLoop()) { hidScanInput(); u32 kHeld = hidKeysHeld(); u32 kDown = hidKeysDown(); if (hidKeysUp()) { time(&t_start); // reset held timer } if (kDown & KEY_DOWN) { picker->file_index++; if (picker->file_index >= picker->file_count) picker->file_index = 0; time(&t_start); } else if (kHeld & KEY_DOWN) { time(&t_end); t_elapsed = t_end - t_start; if (t_elapsed > 0) { picker->file_index++; if (picker->file_index >= picker->file_count) picker->file_index = 0; svcSleep(100); } } if (kDown & KEY_UP) { picker->file_index--; if (picker->file_index < 0) picker->file_index = picker->file_count - 1; time(&t_start); } else if (kHeld & KEY_UP) { time(&t_end); t_elapsed = t_end - t_start; if (t_elapsed > 0) { picker->file_index--; if (picker->file_index < 0) picker->file_index = picker->file_count - 1; svcSleep(100); } } if (kDown & KEY_A) { if (picker->file_count > 0) { int index = picker->file_index; if (!picker->files[index].isDir) { if (confirm(0, "Launch \"%s\" ?", picker->files[index].name)) { strncpy(picked->name, picker->files[index].name, 512); strncpy(picked->path, picker->files[index].path, 512); picked->isDir = picker->files[index].isDir; picked->size = picker->files[index].size; break; } } else { get_dir(picker->files[index].path); } } } else if (kDown & KEY_X) { int index = picker->file_index; if (!picker->files[index].isDir) { const char *ext = get_filename_ext(picker->files[index].name); if (strcasecmp(ext, "3dsx") == 0) { if (confirm(3, "Add entry to boot menu: \"%s\" ?", picker->files[index].name)) { if (config->count > CONFIG_MAX_ENTRIES - 1) { debug("Maximum entries reached (%i)\n", CONFIG_MAX_ENTRIES); } else if (configAddEntry(picker->files[index].name, picker->files[index].path, 0) == 0) { debug("Added entry: %s\n", picker->files[index].name); } else { debug("Error adding entry: %s\n", picker->files[index].name); } } } } } else if (kDown & KEY_B) { // exit if we can't go back if (strlen(picker->now_path) <= 1) break; // remove slash if needed if (end_with(picker->now_path, '/')) picker->now_path[strlen(picker->now_path) - 1] = '\0'; // build path char *slash = strrchr(picker->now_path, '/'); if (slash == NULL) break; int len = (int) (slash - picker->now_path); picker->now_path[len] = '\0'; // enter new dir get_dir(picker->now_path); } drawBg(); drawTitle("*** Select a file ***"); int i, y = 0; int page = picker->file_index / MAX_LINE; for (i = page * MAX_LINE; i < page * MAX_LINE + MAX_LINE; i++) { if (i >= picker->file_count) break; drawItemN(i == picker->file_index, 47, 16 * i, picker->files[i].name); if (i == picker->file_index && !picker->files[i].isDir) { drawInfo("Press (A) to launch\nPress (X) to add to boot menu"); } y++; } gfxSwap(); } free(picker); }