diff --git a/radio/releasenotes.txt b/radio/releasenotes.txt
index 05f7efaca..050ac9ae4 100644
--- a/radio/releasenotes.txt
+++ b/radio/releasenotes.txt
@@ -7,6 +7,7 @@
9XE top LDC fixes: added TX battery blinking on battery warning, fixed display problem when battery voltage lower than batlow value. (#2671)
Timers range extended (it was limited to around 9 hours before) (#2702)
Fixed: Playing two background sounds at once causes sound to stop (#2704)
+Several fixes to the SD card manager menu (#2623)
[Sky9x / 9XR-PRO]
diff --git a/radio/src/gui/Taranis/menu_general_sdmanager.cpp b/radio/src/gui/Taranis/menu_general_sdmanager.cpp
index 95257a827..4dfc3f4db 100755
--- a/radio/src/gui/Taranis/menu_general_sdmanager.cpp
+++ b/radio/src/gui/Taranis/menu_general_sdmanager.cpp
@@ -36,7 +36,10 @@
#include "../../opentx.h"
-#define REFRESH_FILES() reusableBuffer.sdmanager.offset = 65535
+#define REFRESH_FILES() do { reusableBuffer.sdmanager.offset = 65535; m_posVert = 0; } while(0)
+#define NODE_TYPE(fname) fname[SD_SCREEN_FILE_LENGTH+1]
+#define IS_DIRECTORY(fname) ((bool)(!NODE_TYPE(fname)))
+#define IS_FILE(fname) ((bool)(NODE_TYPE(fname)))
void menuGeneralSdManagerInfo(uint8_t event)
{
@@ -66,12 +69,12 @@ void menuGeneralSdManagerInfo(uint8_t event)
inline bool isFilenameGreater(bool isfile, const char * fn, const char * line)
{
- return (isfile && !line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) > 0);
+ return (isfile && IS_DIRECTORY(line)) || (isfile==IS_FILE(line) && strcasecmp(fn, line) > 0);
}
inline bool isFilenameLower(bool isfile, const char * fn, const char * line)
{
- return (!isfile && line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) < 0);
+ return (!isfile && IS_FILE(line)) || (isfile==IS_FILE(line) && strcasecmp(fn, line) < 0);
}
bool isBootloader(const char *filename)
@@ -172,19 +175,31 @@ void onSdManagerMenu(const char *result)
}
else if (result == STR_PASTE) {
f_getcwd(lfn, _MAX_LFN);
- POPUP_WARNING(fileCopy(clipboard.data.sd.filename, clipboard.data.sd.directory, lfn));
- REFRESH_FILES();
+ // if destination is dir, copy into that dir
+ if (IS_DIRECTORY(line)) {
+ strcat(lfn, PSTR("/"));
+ strcat(lfn, line);
+ }
+ if (strcmp(clipboard.data.sd.directory, lfn)) { // prevent copying to the same directory
+ POPUP_WARNING(fileCopy(clipboard.data.sd.filename, clipboard.data.sd.directory, lfn));
+ REFRESH_FILES();
+ }
}
else if (result == STR_RENAME_FILE) {
+ memcpy(reusableBuffer.sdmanager.originalName, line, sizeof(reusableBuffer.sdmanager.originalName));
char *ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1);
if (ext) {
- memcpy(reusableBuffer.sdmanager.originalName, line, sizeof(reusableBuffer.sdmanager.originalName));
// write spaces to allow a longer filename
memset(ext, ' ', SD_SCREEN_FILE_LENGTH-LEN_FILE_EXTENSION-(ext-line));
line[SD_SCREEN_FILE_LENGTH-LEN_FILE_EXTENSION] = '\0';
- s_editMode = EDIT_MODIFY_STRING;
- editNameCursorPos = 0;
}
+ else {
+ int len = strlen(line);
+ memset(line + strlen(line), ' ', SD_SCREEN_FILE_LENGTH - len);
+ line[SD_SCREEN_FILE_LENGTH] = '\0';
+ }
+ s_editMode = EDIT_MODIFY_STRING;
+ editNameCursorPos = 0;
}
else if (result == STR_DELETE_FILE) {
getSelectionFullPath(lfn);
@@ -193,9 +208,6 @@ void onSdManagerMenu(const char *result)
strcpy_P(statusLineMsg+min((uint8_t)strlen(statusLineMsg), (uint8_t)13), STR_REMOVED);
showStatusLine();
REFRESH_FILES();
- if (m_posVert == reusableBuffer.sdmanager.count-1) {
- m_posVert--;
- }
}
else if (result == STR_PLAY_FILE) {
getSelectionFullPath(lfn);
@@ -279,7 +291,7 @@ void menuGeneralSdManager(uint8_t _event)
break;
}
else {
- if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) {
+ if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[index])) {
f_chdir(reusableBuffer.sdmanager.lines[index]);
s_pgOfs = 0;
m_posVert = 1;
@@ -296,6 +308,9 @@ void menuGeneralSdManager(uint8_t _event)
killEvents(_event);
char *line = reusableBuffer.sdmanager.lines[index];
char *ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1);
+ if (!strcmp(line, "..")) {
+ break; // no menu for parent dir
+ }
if (ext) {
if (!strcasecmp(ext, SOUNDS_EXT)) {
MENU_ADD_ITEM(STR_PLAY_FILE);
@@ -326,12 +341,13 @@ void menuGeneralSdManager(uint8_t _event)
}
}
if (!READ_ONLY()) {
- if (line[SD_SCREEN_FILE_LENGTH+1]) // it's a file
+ if (IS_FILE(line)) // it's a file
MENU_ADD_ITEM(STR_COPY_FILE);
if (clipboard.type == CLIPBOARD_TYPE_SD_FILE)
MENU_ADD_ITEM(STR_PASTE);
MENU_ADD_ITEM(STR_RENAME_FILE);
- MENU_ADD_ITEM(STR_DELETE_FILE);
+ if (IS_FILE(line))
+ MENU_ADD_ITEM(STR_DELETE_FILE);
}
menuHandler = onSdManagerMenu;
}
@@ -357,7 +373,7 @@ void menuGeneralSdManager(uint8_t _event)
else if (s_pgOfs > reusableBuffer.sdmanager.offset) {
memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], 6*sizeof(reusableBuffer.sdmanager.lines[0]));
memset(reusableBuffer.sdmanager.lines[6], 0xff, SD_SCREEN_FILE_LENGTH);
- reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = 1;
+ NODE_TYPE(reusableBuffer.sdmanager.lines[6]) = 1;
}
else {
memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], 6*sizeof(reusableBuffer.sdmanager.lines[0]));
@@ -388,9 +404,9 @@ void menuGeneralSdManager(uint8_t _event)
char *line = reusableBuffer.sdmanager.lines[i];
if (line[0] == '\0' || isFilenameLower(isfile, fn, line)) {
if (i < 6) memmove(reusableBuffer.sdmanager.lines[i+1], line, sizeof(reusableBuffer.sdmanager.lines[i]) * (6-i));
- memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i]));
+ memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(line, fn);
- line[SD_SCREEN_FILE_LENGTH+1] = isfile;
+ NODE_TYPE(line) = isfile;
break;
}
}
@@ -400,9 +416,9 @@ void menuGeneralSdManager(uint8_t _event)
char *line = reusableBuffer.sdmanager.lines[i];
if (line[0] == '\0' || isFilenameGreater(isfile, fn, line)) {
if (i > 0) memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], sizeof(reusableBuffer.sdmanager.lines[0]) * i);
- memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i]));
+ memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(line, fn);
- line[SD_SCREEN_FILE_LENGTH+1] = isfile;
+ NODE_TYPE(line) = isfile;
break;
}
}
@@ -411,14 +427,14 @@ void menuGeneralSdManager(uint8_t _event)
if (isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[5]) && isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[6])) {
memset(reusableBuffer.sdmanager.lines[6], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(reusableBuffer.sdmanager.lines[6], fn);
- reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = isfile;
+ NODE_TYPE(reusableBuffer.sdmanager.lines[6]) = isfile;
}
}
else {
if (isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[0])) {
memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(reusableBuffer.sdmanager.lines[0], fn);
- reusableBuffer.sdmanager.lines[0][SD_SCREEN_FILE_LENGTH+1] = isfile;
+ NODE_TYPE(reusableBuffer.sdmanager.lines[0]) = isfile;
}
}
}
@@ -432,7 +448,7 @@ void menuGeneralSdManager(uint8_t _event)
lcdNextPos = 0;
LcdFlags attr = (index == i ? BSS|INVERS : BSS);
if (reusableBuffer.sdmanager.lines[i][0]) {
- if (!reusableBuffer.sdmanager.lines[i][SD_SCREEN_FILE_LENGTH+1]) { lcd_putcAtt(0, y, '[', s_editMode == EDIT_MODIFY_STRING ? 0 : attr); }
+ if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) { lcd_putcAtt(0, y, '[', s_editMode == EDIT_MODIFY_STRING ? 0 : attr); }
if (s_editMode == EDIT_MODIFY_STRING && attr) {
editName(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], SD_SCREEN_FILE_LENGTH-4, _event, attr, 0);
if (s_editMode == 0) {
@@ -441,6 +457,9 @@ void menuGeneralSdManager(uint8_t _event)
if (ext) {
strAppend(&reusableBuffer.sdmanager.lines[i][len], ext);
}
+ else {
+ reusableBuffer.sdmanager.lines[i][len] = 0;
+ }
f_rename(reusableBuffer.sdmanager.originalName, reusableBuffer.sdmanager.lines[i]);
REFRESH_FILES();
}
@@ -448,7 +467,7 @@ void menuGeneralSdManager(uint8_t _event)
else {
lcd_putsAtt(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], attr);
}
- if (!reusableBuffer.sdmanager.lines[i][SD_SCREEN_FILE_LENGTH+1]) { lcd_putcAtt(lcdNextPos, y, ']', s_editMode == EDIT_MODIFY_STRING ? 0 : attr); }
+ if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) { lcd_putcAtt(lcdNextPos, y, ']', s_editMode == EDIT_MODIFY_STRING ? 0 : attr); }
}
}
diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp
index 6f108351b..a74e3fad1 100644
--- a/radio/src/targets/simu/simpgmspace.cpp
+++ b/radio/src/targets/simu/simpgmspace.cpp
@@ -929,14 +929,24 @@ FRESULT f_mkdir (const TCHAR*)
return FR_OK;
}
-FRESULT f_unlink (const TCHAR*)
+FRESULT f_unlink (const TCHAR* name)
{
+ char *path = convertSimuPath(name);
+ if (unlink(path)) {
+ TRACE("f_unlink(%s) = error %d (%s)", path, errno, strerror(errno));
+ return FR_INVALID_NAME;
+ }
+ TRACE("f_unlink(%s) = OK", path);
return FR_OK;
}
FRESULT f_rename(const TCHAR *oldname, const TCHAR *newname)
{
- TRACE("f_rename(%s, %s)", oldname, newname);
+ if (rename(oldname, newname) < 0) {
+ TRACE("f_rename(%s, %s) = error %d (%s)", oldname, newname, errno, strerror(errno));
+ return FR_INVALID_NAME;
+ }
+ TRACE("f_rename(%s, %s) = OK", oldname, newname);
return FR_OK;
}
@@ -966,7 +976,12 @@ int f_printf (FIL *fil, const TCHAR * format, ...)
FRESULT f_getcwd (TCHAR *path, UINT sz_path)
{
- strcpy(path, ".");
+ // remove simuSdDirectory from the cwd
+ char * cwd = get_current_dir_name();
+ std::string c(cwd + strlen(simuSdDirectory));
+ free(cwd);
+ strcpy(path, c.c_str());
+ TRACE("f_getcwd() = %s", path);
return FR_OK;
}