mirror of https://gitlab.com/nakst/essence
basic file cut and paste
This commit is contained in:
parent
fdc4da053b
commit
6c106d1a1f
|
@ -62,7 +62,7 @@ void CommandRename(Instance *instance, EsElement *, EsCommand *) {
|
||||||
size_t oldPathBytes;
|
size_t oldPathBytes;
|
||||||
char *oldPath = EsStringAllocateAndFormat(&oldPathBytes, "%s%s", STRFMT(instance->folder->path), STRFMT(task->string2));
|
char *oldPath = EsStringAllocateAndFormat(&oldPathBytes, "%s%s", STRFMT(instance->folder->path), STRFMT(task->string2));
|
||||||
|
|
||||||
FolderPathMoved(instance, { .text = oldPath, .bytes = oldPathBytes }, { .text = newPath, .bytes = newPathBytes });
|
FolderPathMoved(instance, { .text = oldPath, .bytes = oldPathBytes }, { .text = newPath, .bytes = newPathBytes }, true);
|
||||||
|
|
||||||
EsDirectoryChild information = {};
|
EsDirectoryChild information = {};
|
||||||
EsPathQueryInformation(newPath, newPathBytes, &information);
|
EsPathQueryInformation(newPath, newPathBytes, &information);
|
||||||
|
@ -119,7 +119,7 @@ void CommandNewFolder(Instance *instance, EsElement *, EsCommand *) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
void CommandCopyOrCut(Instance *instance, uint32_t flags) {
|
||||||
// TODO If copying a single file, copy the data of the file (as well as its path),
|
// TODO If copying a single file, copy the data of the file (as well as its path),
|
||||||
// so that document can be pasted into other applications.
|
// so that document can be pasted into other applications.
|
||||||
|
|
||||||
|
@ -141,10 +141,14 @@ void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
||||||
EsBufferFlushToFileStore(&buffer);
|
EsBufferFlushToFileStore(&buffer);
|
||||||
|
|
||||||
EsPoint point = EsListViewGetAnnouncementPointForSelection(instance->list);
|
EsPoint point = EsListViewGetAnnouncementPointForSelection(instance->list);
|
||||||
EsError error = EsClipboardCloseAndAdd(ES_CLIPBOARD_PRIMARY, ES_CLIPBOARD_FORMAT_PATH_LIST, buffer.fileStore);
|
EsError error = EsClipboardCloseAndAdd(ES_CLIPBOARD_PRIMARY, ES_CLIPBOARD_FORMAT_PATH_LIST, buffer.fileStore, flags);
|
||||||
|
|
||||||
if (error == ES_SUCCESS) {
|
if (error == ES_SUCCESS) {
|
||||||
|
if (flags & ES_CLIPBOARD_ADD_LAZY_CUT) {
|
||||||
|
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementCut));
|
||||||
|
} else {
|
||||||
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementCopied));
|
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementCopied));
|
||||||
|
}
|
||||||
} else if (error == ES_ERROR_INSUFFICIENT_RESOURCES || error == ES_ERROR_DRIVE_FULL) {
|
} else if (error == ES_ERROR_INSUFFICIENT_RESOURCES || error == ES_ERROR_DRIVE_FULL) {
|
||||||
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementCopyErrorResources));
|
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementCopyErrorResources));
|
||||||
} else {
|
} else {
|
||||||
|
@ -152,15 +156,30 @@ void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EsError CommandPasteFile(String source, String destinationBase, void **copyBuffer, String *_destination = nullptr) {
|
void CommandCut(Instance *instance, EsElement *, EsCommand *) {
|
||||||
|
CommandCopyOrCut(instance, ES_CLIPBOARD_ADD_LAZY_CUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
||||||
|
CommandCopyOrCut(instance, ES_FLAGS_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
EsError CommandPasteFile(String source, String destinationBase, void **copyBuffer, bool move, String *_destination) {
|
||||||
if (PathHasPrefix(destinationBase, source)) {
|
if (PathHasPrefix(destinationBase, source)) {
|
||||||
return ES_ERROR_TARGET_WITHIN_SOURCE;
|
return ES_ERROR_TARGET_WITHIN_SOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = PathGetName(source);
|
String name = PathGetName(source);
|
||||||
String destination = StringAllocateAndFormat("%s%z%s", STRFMT(destinationBase), PathHasTrailingSlash(destinationBase) ? "" : "/", STRFMT(name));
|
String destination = StringAllocateAndFormat("%s%z%s", STRFMT(destinationBase), PathHasTrailingSlash(destinationBase) ? "" : "/", STRFMT(name));
|
||||||
|
EsError error;
|
||||||
|
|
||||||
if (StringEquals(PathGetParent(source), destinationBase)) {
|
if (StringEquals(PathGetParent(source), destinationBase)) {
|
||||||
|
if (move) {
|
||||||
|
// Move with the source and destination folders identical; meaningless.
|
||||||
|
error = ES_SUCCESS;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
destination.allocated += 32;
|
destination.allocated += 32;
|
||||||
destination.text = (char *) EsHeapReallocate(destination.text, destination.allocated, false);
|
destination.text = (char *) EsHeapReallocate(destination.text, destination.allocated, false);
|
||||||
size_t bytes = EsPathFindUniqueName(destination.text, destination.bytes, destination.allocated);
|
size_t bytes = EsPathFindUniqueName(destination.text, destination.bytes, destination.allocated);
|
||||||
|
@ -174,8 +193,18 @@ EsError CommandPasteFile(String source, String destinationBase, void **copyBuffe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EsPrint("Copying %s -> %s...\n", STRFMT(source), STRFMT(destination));
|
EsPrint("%z %s -> %s...\n", move ? "Moving" : "Copying", STRFMT(source), STRFMT(destination));
|
||||||
EsError error = EsFileCopy(STRING(source), STRING(destination), copyBuffer);
|
|
||||||
|
if (move) {
|
||||||
|
error = EsPathMove(STRING(source), STRING(destination), ES_FLAGS_DEFAULT);
|
||||||
|
|
||||||
|
if (error == ES_ERROR_VOLUME_MISMATCH) {
|
||||||
|
// TODO Delete the files after all copies complete successfully.
|
||||||
|
error = EsFileCopy(STRING(source), STRING(destination), copyBuffer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error = EsFileCopy(STRING(source), STRING(destination), copyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (error == ES_ERROR_INCORRECT_NODE_TYPE) {
|
if (error == ES_ERROR_INCORRECT_NODE_TYPE) {
|
||||||
EsDirectoryChild *buffer;
|
EsDirectoryChild *buffer;
|
||||||
|
@ -190,7 +219,7 @@ EsError CommandPasteFile(String source, String destinationBase, void **copyBuffe
|
||||||
for (intptr_t i = 0; i < childCount && error == ES_SUCCESS; i++) {
|
for (intptr_t i = 0; i < childCount && error == ES_SUCCESS; i++) {
|
||||||
String childSourcePath = StringAllocateAndFormat("%s%z%s", STRFMT(source),
|
String childSourcePath = StringAllocateAndFormat("%s%z%s", STRFMT(source),
|
||||||
PathHasTrailingSlash(source) ? "" : "/", buffer[i].nameBytes, buffer[i].name);
|
PathHasTrailingSlash(source) ? "" : "/", buffer[i].nameBytes, buffer[i].name);
|
||||||
error = CommandPasteFile(childSourcePath, destination, copyBuffer);
|
error = CommandPasteFile(childSourcePath, destination, copyBuffer, move, nullptr);
|
||||||
StringDestroy(&childSourcePath);
|
StringDestroy(&childSourcePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,9 +229,15 @@ EsError CommandPasteFile(String source, String destinationBase, void **copyBuffe
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == ES_SUCCESS) {
|
if (error == ES_SUCCESS) {
|
||||||
|
if (move) {
|
||||||
|
FolderFileUpdatedAtPath(source, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
FolderFileUpdatedAtPath(destination, nullptr);
|
FolderFileUpdatedAtPath(destination, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:;
|
||||||
|
|
||||||
if (_destination && error == ES_SUCCESS) {
|
if (_destination && error == ES_SUCCESS) {
|
||||||
*_destination = destination;
|
*_destination = destination;
|
||||||
} else {
|
} else {
|
||||||
|
@ -212,6 +247,10 @@ EsError CommandPasteFile(String source, String destinationBase, void **copyBuffe
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PasteOperation {
|
||||||
|
String source, destination;
|
||||||
|
};
|
||||||
|
|
||||||
void CommandPaste(Instance *instance, EsElement *, EsCommand *) {
|
void CommandPaste(Instance *instance, EsElement *, EsCommand *) {
|
||||||
if (EsClipboardHasFormat(ES_CLIPBOARD_PRIMARY, ES_CLIPBOARD_FORMAT_PATH_LIST)) {
|
if (EsClipboardHasFormat(ES_CLIPBOARD_PRIMARY, ES_CLIPBOARD_FORMAT_PATH_LIST)) {
|
||||||
// TODO Background task.
|
// TODO Background task.
|
||||||
|
@ -223,9 +262,14 @@ void CommandPaste(Instance *instance, EsElement *, EsCommand *) {
|
||||||
void *copyBuffer = nullptr;
|
void *copyBuffer = nullptr;
|
||||||
|
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
char *pathList = EsClipboardReadText(ES_CLIPBOARD_PRIMARY, &bytes);
|
uint32_t flags;
|
||||||
|
char *pathList = EsClipboardReadText(ES_CLIPBOARD_PRIMARY, &bytes, &flags);
|
||||||
|
|
||||||
Array<String> itemsToSelect = {};
|
bool move = flags & ES_CLIPBOARD_ADD_LAZY_CUT;
|
||||||
|
String destinationBase = StringDuplicate(instance->folder->path);
|
||||||
|
Array<PasteOperation> pasteOperations = {};
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
if (pathList) {
|
if (pathList) {
|
||||||
const char *position = pathList;
|
const char *position = pathList;
|
||||||
|
@ -237,13 +281,12 @@ void CommandPaste(Instance *instance, EsElement *, EsCommand *) {
|
||||||
String source = StringFromLiteralWithSize(position, newline - position);
|
String source = StringFromLiteralWithSize(position, newline - position);
|
||||||
String destination;
|
String destination;
|
||||||
|
|
||||||
if (ES_SUCCESS != CommandPasteFile(source, instance->folder->path, ©Buffer, &destination)) {
|
if (ES_SUCCESS != CommandPasteFile(source, destinationBase, ©Buffer, move, &destination)) {
|
||||||
goto encounteredError;
|
goto encounteredError;
|
||||||
}
|
}
|
||||||
|
|
||||||
String destinationItem = StringDuplicate(PathGetName(destination));
|
PasteOperation operation = { .source = StringDuplicate(source), .destination = destination };
|
||||||
itemsToSelect.Add(destinationItem);
|
pasteOperations.Add(operation);
|
||||||
StringDestroy(&destination);
|
|
||||||
|
|
||||||
position += source.bytes + 1;
|
position += source.bytes + 1;
|
||||||
bytes -= source.bytes + 1;
|
bytes -= source.bytes + 1;
|
||||||
|
@ -252,25 +295,47 @@ void CommandPaste(Instance *instance, EsElement *, EsCommand *) {
|
||||||
encounteredError:;
|
encounteredError:;
|
||||||
EsPoint point = EsListViewGetAnnouncementPointForSelection(instance->list);
|
EsPoint point = EsListViewGetAnnouncementPointForSelection(instance->list);
|
||||||
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementPasteErrorOther));
|
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementPasteErrorOther));
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t pathSectionCount = PathCountSections(instance->folder->path);
|
size_t pathSectionCount = PathCountSections(destinationBase);
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < pathSectionCount - 1; i++) {
|
for (uintptr_t i = 0; i < pathSectionCount; i++) {
|
||||||
String parent = PathGetParent(instance->folder->path, i + 1);
|
String parent = PathGetParent(destinationBase, i + 1);
|
||||||
FolderFileUpdatedAtPath(parent, nullptr);
|
FolderFileUpdatedAtPath(parent, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
EsListViewSelectNone(instance->list);
|
if (pasteOperations.Length()) {
|
||||||
|
size_t pathSectionCount = PathCountSections(pasteOperations[0].source);
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < itemsToSelect.Length(); i++) {
|
for (uintptr_t i = 0; i < pathSectionCount; i++) {
|
||||||
InstanceSelectByName(instance, itemsToSelect[i], true, i == itemsToSelect.Length() - 1);
|
String parent = PathGetParent(pasteOperations[0].source, i + 1);
|
||||||
StringDestroy(&itemsToSelect[i]);
|
FolderFileUpdatedAtPath(parent, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
EsListViewSelectNone(instance->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uintptr_t i = 0; i < pasteOperations.Length(); i++) {
|
||||||
|
if (success) {
|
||||||
|
InstanceSelectByName(instance, PathGetName(pasteOperations[i].destination), true, i == pasteOperations.Length() - 1);
|
||||||
|
|
||||||
|
if (move) {
|
||||||
|
// TODO We must do this regardless of whether the instance has been destroyed during the operation.
|
||||||
|
FolderPathMoved(instance, pasteOperations[i].source, pasteOperations[i].destination, i == pasteOperations.Length() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringDestroy(&pasteOperations[i].source);
|
||||||
|
StringDestroy(&pasteOperations[i].destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
EsHeapFree(pathList);
|
EsHeapFree(pathList);
|
||||||
EsHeapFree(copyBuffer);
|
EsHeapFree(copyBuffer);
|
||||||
itemsToSelect.Free();
|
StringDestroy(&destinationBase);
|
||||||
|
pasteOperations.Free();
|
||||||
} else {
|
} else {
|
||||||
// TODO Paste the data into a new file.
|
// TODO Paste the data into a new file.
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,7 @@ NamespaceHandler namespaceHandlers[] = {
|
||||||
{
|
{
|
||||||
.type = NAMESPACE_HANDLER_FILE_SYSTEM,
|
.type = NAMESPACE_HANDLER_FILE_SYSTEM,
|
||||||
.rootContainerHandlerType = NAMESPACE_HANDLER_DRIVES_PAGE,
|
.rootContainerHandlerType = NAMESPACE_HANDLER_DRIVES_PAGE,
|
||||||
|
.canCut = true,
|
||||||
.canCopy = true,
|
.canCopy = true,
|
||||||
.canPaste = true,
|
.canPaste = true,
|
||||||
.handlesPath = FSDirHandlesPath,
|
.handlesPath = FSDirHandlesPath,
|
||||||
|
@ -426,29 +427,6 @@ void FolderAddEntryAndUpdateInstances(Folder *folder, const char *name, size_t n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderFileUpdatedAtPath(String path, Instance *instance) {
|
|
||||||
path = PathRemoveTrailingSlash(path);
|
|
||||||
String file = PathGetName(path);
|
|
||||||
String folder = PathGetParent(path);
|
|
||||||
EsDirectoryChild information = {};
|
|
||||||
|
|
||||||
if (EsPathQueryInformation(STRING(path), &information)) {
|
|
||||||
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
|
||||||
if (loadedFolders[i]->itemHandler->type != NAMESPACE_HANDLER_FILE_SYSTEM) continue;
|
|
||||||
if (EsStringCompareRaw(STRING(loadedFolders[i]->path), STRING(folder))) continue;
|
|
||||||
|
|
||||||
EsMutexAcquire(&loadedFolders[i]->modifyEntriesMutex);
|
|
||||||
|
|
||||||
if (loadedFolders[i]->doneInitialEnumeration) {
|
|
||||||
FolderAddEntryAndUpdateInstances(loadedFolders[i], file.text, file.bytes, &information, instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
EsMutexRelease(&loadedFolders[i]->modifyEntriesMutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t FolderRemoveEntryAndUpdateInstances(Folder *folder, const char *name, size_t nameBytes) {
|
uint64_t FolderRemoveEntryAndUpdateInstances(Folder *folder, const char *name, size_t nameBytes) {
|
||||||
FolderEntry *entry = (FolderEntry *) HashTableGetLong(&folder->entries, name, nameBytes);
|
FolderEntry *entry = (FolderEntry *) HashTableGetLong(&folder->entries, name, nameBytes);
|
||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
|
@ -466,7 +444,32 @@ uint64_t FolderRemoveEntryAndUpdateInstances(Folder *folder, const char *name, s
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderPathMoved(Instance *instance, String oldPath, String newPath) {
|
void FolderFileUpdatedAtPath(String path, Instance *instance) {
|
||||||
|
path = PathRemoveTrailingSlash(path);
|
||||||
|
String file = PathGetName(path);
|
||||||
|
String folder = PathGetParent(path);
|
||||||
|
EsDirectoryChild information = {};
|
||||||
|
bool add = EsPathQueryInformation(STRING(path), &information);
|
||||||
|
|
||||||
|
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
||||||
|
if (loadedFolders[i]->itemHandler->type != NAMESPACE_HANDLER_FILE_SYSTEM) continue;
|
||||||
|
if (EsStringCompareRaw(STRING(loadedFolders[i]->path), STRING(folder))) continue;
|
||||||
|
|
||||||
|
EsMutexAcquire(&loadedFolders[i]->modifyEntriesMutex);
|
||||||
|
|
||||||
|
if (loadedFolders[i]->doneInitialEnumeration) {
|
||||||
|
if (add) {
|
||||||
|
FolderAddEntryAndUpdateInstances(loadedFolders[i], file.text, file.bytes, &information, instance);
|
||||||
|
} else {
|
||||||
|
FolderRemoveEntryAndUpdateInstances(loadedFolders[i], file.text, file.bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EsMutexRelease(&loadedFolders[i]->modifyEntriesMutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderPathMoved(Instance *instance, String oldPath, String newPath, bool saveConfiguration) {
|
||||||
_EsPathAnnouncePathMoved(instance, STRING(oldPath), STRING(newPath));
|
_EsPathAnnouncePathMoved(instance, STRING(oldPath), STRING(newPath));
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
|
||||||
|
@ -523,7 +526,9 @@ void FolderPathMoved(Instance *instance, String oldPath, String newPath) {
|
||||||
"%s%s", STRFMT(newPath), STRFMT(after));
|
"%s%s", STRFMT(newPath), STRFMT(after));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (saveConfiguration) {
|
||||||
ConfigurationSave();
|
ConfigurationSave();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FolderAttachInstance(Instance *instance, String path, bool recurse) {
|
void FolderAttachInstance(Instance *instance, String path, bool recurse) {
|
||||||
|
|
|
@ -182,7 +182,7 @@ struct NamespaceHandler {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t rootContainerHandlerType;
|
uint8_t rootContainerHandlerType;
|
||||||
|
|
||||||
bool canCopy, canPaste;
|
bool canCut, canCopy, canPaste;
|
||||||
|
|
||||||
bool (*handlesPath)(String path);
|
bool (*handlesPath)(String path);
|
||||||
|
|
||||||
|
|
|
@ -175,8 +175,11 @@ void InstanceUpdateItemSelectionCountCommands(Instance *instance) {
|
||||||
EsCommandSetEnabled(command, enabled); \
|
EsCommandSetEnabled(command, enabled); \
|
||||||
EsCommandSetCallback(command, callback); } while(0)
|
EsCommandSetCallback(command, callback); } while(0)
|
||||||
|
|
||||||
|
if (EsElementIsFocused(instance->list)) {
|
||||||
|
COMMAND_SET(ES_COMMAND_CUT, CommandCut, instance->selectedItemCount >= 1 && instance->folder->itemHandler->canCut && !instance->folder->readOnly);
|
||||||
COMMAND_SET(ES_COMMAND_COPY, CommandCopy, instance->selectedItemCount >= 1 && instance->folder->itemHandler->canCopy);
|
COMMAND_SET(ES_COMMAND_COPY, CommandCopy, instance->selectedItemCount >= 1 && instance->folder->itemHandler->canCopy);
|
||||||
COMMAND_SET(ES_COMMAND_PASTE, CommandPaste, instance->folder->itemHandler->canPaste && EsClipboardHasData(ES_CLIPBOARD_PRIMARY) && !instance->folder->readOnly);
|
COMMAND_SET(ES_COMMAND_PASTE, CommandPaste, instance->folder->itemHandler->canPaste && EsClipboardHasData(ES_CLIPBOARD_PRIMARY) && !instance->folder->readOnly);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstanceCompareFolderEntries(FolderEntry *left, FolderEntry *right, uint16_t sortColumn) {
|
int InstanceCompareFolderEntries(FolderEntry *left, FolderEntry *right, uint16_t sortColumn) {
|
||||||
|
@ -703,7 +706,9 @@ int ListCallback(EsElement *element, EsMessage *message) {
|
||||||
InstanceUpdateItemSelectionCountCommands(instance);
|
InstanceUpdateItemSelectionCountCommands(instance);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (message->type == ES_MSG_FOCUSED_END) {
|
} else if (message->type == ES_MSG_FOCUSED_END) {
|
||||||
|
EsCommandSetCallback(EsCommandByID(instance, ES_COMMAND_CUT), nullptr);
|
||||||
EsCommandSetCallback(EsCommandByID(instance, ES_COMMAND_COPY), nullptr);
|
EsCommandSetCallback(EsCommandByID(instance, ES_COMMAND_COPY), nullptr);
|
||||||
|
EsCommandSetCallback(EsCommandByID(instance, ES_COMMAND_PASTE), nullptr);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT) {
|
} else if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT) {
|
||||||
int column = message->getContent.column, index = message->getContent.index;
|
int column = message->getContent.column, index = message->getContent.index;
|
||||||
|
|
|
@ -5408,6 +5408,10 @@ void UIMaybeRemoveFocusedElement(EsWindow *window) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EsElementIsFocused(EsElement *element) {
|
||||||
|
return element->window->focused == element;
|
||||||
|
}
|
||||||
|
|
||||||
void EsElementFocus(EsElement *element, uint32_t flags) {
|
void EsElementFocus(EsElement *element, uint32_t flags) {
|
||||||
EsMessageMutexCheck();
|
EsMessageMutexCheck();
|
||||||
|
|
||||||
|
|
|
@ -483,6 +483,7 @@ struct EsListView : EsElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Populate() {
|
void Populate() {
|
||||||
|
#if 0
|
||||||
EsPrint("--- Before Populate() ---\n");
|
EsPrint("--- Before Populate() ---\n");
|
||||||
EsPrint("Scroll: %i\n", (int) (scroll.position[1] - currentStyle->insets.t));
|
EsPrint("Scroll: %i\n", (int) (scroll.position[1] - currentStyle->insets.t));
|
||||||
|
|
||||||
|
@ -498,6 +499,7 @@ struct EsListView : EsElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
EsPrint("------\n");
|
EsPrint("------\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO Keep one item before and after the viewport, so tab traversal on custom elements works.
|
// TODO Keep one item before and after the viewport, so tab traversal on custom elements works.
|
||||||
// TODO Always keep an item if it has FOCUS_WITHIN.
|
// TODO Always keep an item if it has FOCUS_WITHIN.
|
||||||
|
@ -2507,7 +2509,8 @@ void EsListViewSetMaximumItemsPerBand(EsListView *view, int maximumItemsPerBand)
|
||||||
}
|
}
|
||||||
|
|
||||||
EsPoint EsListViewGetAnnouncementPointForSelection(EsListView *view) {
|
EsPoint EsListViewGetAnnouncementPointForSelection(EsListView *view) {
|
||||||
EsRectangle bounding = EsElementGetWindowBounds(view);
|
EsRectangle viewWindowBounds = EsElementGetWindowBounds(view);
|
||||||
|
EsRectangle bounding = viewWindowBounds;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < view->visibleItems.Length(); i++) {
|
for (uintptr_t i = 0; i < view->visibleItems.Length(); i++) {
|
||||||
|
@ -2518,5 +2521,6 @@ EsPoint EsListViewGetAnnouncementPointForSelection(EsListView *view) {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bounding = EsRectangleIntersection(bounding, viewWindowBounds);
|
||||||
return ES_POINT((bounding.l + bounding.r) / 2, (bounding.t + bounding.b) / 2);
|
return ES_POINT((bounding.l + bounding.r) / 2, (bounding.t + bounding.b) / 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -729,6 +729,8 @@ define ES_VOLUME_READ_ONLY (1 << 0)
|
||||||
|
|
||||||
define ES_PATH_MOVE_ALLOW_COPY_AND_DELETE (1 << 0) // Copy and delete the file if a direct move is not possible.
|
define ES_PATH_MOVE_ALLOW_COPY_AND_DELETE (1 << 0) // Copy and delete the file if a direct move is not possible.
|
||||||
|
|
||||||
|
define ES_CLIPBOARD_ADD_LAZY_CUT (1 << 0) // Only perform the deletion after pasting; often implemented as a move.
|
||||||
|
|
||||||
include desktop/icons.header
|
include desktop/icons.header
|
||||||
|
|
||||||
enum EsFatalError {
|
enum EsFatalError {
|
||||||
|
@ -2230,9 +2232,9 @@ function int EsCRTvsnprintf(char *buffer, size_t bufferSize, const char *format,
|
||||||
function EsError EsClipboardAddText(EsClipboard clipboard, STRING text = BLANK_STRING);
|
function EsError EsClipboardAddText(EsClipboard clipboard, STRING text = BLANK_STRING);
|
||||||
function bool EsClipboardHasFormat(EsClipboard clipboard, EsClipboardFormat format);
|
function bool EsClipboardHasFormat(EsClipboard clipboard, EsClipboardFormat format);
|
||||||
function bool EsClipboardHasData(EsClipboard clipboard);
|
function bool EsClipboardHasData(EsClipboard clipboard);
|
||||||
function char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes); // Free with EsHeapFree.
|
function char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes, uint32_t *flags = nullptr); // Free with EsHeapFree.
|
||||||
function EsFileStore *EsClipboardOpen(EsClipboard clipboard); // Open the clipboard for writing.
|
function EsFileStore *EsClipboardOpen(EsClipboard clipboard); // Open the clipboard for writing.
|
||||||
function EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format, EsFileStore *fileStore);
|
function EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format, EsFileStore *fileStore, uint32_t flags = ES_FLAGS_DEFAULT);
|
||||||
|
|
||||||
function void EsUndoClear(EsUndoManager *manager);
|
function void EsUndoClear(EsUndoManager *manager);
|
||||||
function void EsUndoContinueGroup(EsUndoManager *manager);
|
function void EsUndoContinueGroup(EsUndoManager *manager);
|
||||||
|
@ -2277,6 +2279,7 @@ function EsMessage *EsMessageReceive();
|
||||||
|
|
||||||
function void EsElementDraw(EsElement *element, EsPainter *painter); // Actually draw an element onto a painter.
|
function void EsElementDraw(EsElement *element, EsPainter *painter); // Actually draw an element onto a painter.
|
||||||
function void EsElementFocus(EsElement *element, uint32_t flags = ES_FLAGS_DEFAULT);
|
function void EsElementFocus(EsElement *element, uint32_t flags = ES_FLAGS_DEFAULT);
|
||||||
|
function bool EsElementIsFocused(EsElement *element);
|
||||||
function void EsElementSetDisabled(EsElement *element, bool disabled = true);
|
function void EsElementSetDisabled(EsElement *element, bool disabled = true);
|
||||||
function void EsElementSetHidden(EsElement *element, bool hidden = true);
|
function void EsElementSetHidden(EsElement *element, bool hidden = true);
|
||||||
function void EsElementSetCallback(EsElement *element, EsUICallbackFunction callback);
|
function void EsElementSetCallback(EsElement *element, EsUICallbackFunction callback);
|
||||||
|
|
|
@ -502,6 +502,10 @@ EsError EsPathMove(const char *oldPath, ptrdiff_t oldPathBytes, const char *newP
|
||||||
if (oldPathBytes == -1) oldPathBytes = EsCStringLength(oldPath);
|
if (oldPathBytes == -1) oldPathBytes = EsCStringLength(oldPath);
|
||||||
if (newPathBytes == -1) newPathBytes = EsCStringLength(newPath);
|
if (newPathBytes == -1) newPathBytes = EsCStringLength(newPath);
|
||||||
|
|
||||||
|
if (newPathBytes && newPath[newPathBytes - 1] == '/') {
|
||||||
|
newPathBytes--;
|
||||||
|
}
|
||||||
|
|
||||||
_EsNodeInformation node = {};
|
_EsNodeInformation node = {};
|
||||||
_EsNodeInformation directory = {};
|
_EsNodeInformation directory = {};
|
||||||
EsError error;
|
EsError error;
|
||||||
|
@ -756,6 +760,7 @@ struct ClipboardInformation {
|
||||||
uint8_t desktopMessageTag;
|
uint8_t desktopMessageTag;
|
||||||
intptr_t error;
|
intptr_t error;
|
||||||
EsClipboardFormat format;
|
EsClipboardFormat format;
|
||||||
|
uint32_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
EsFileStore *EsClipboardOpen(EsClipboard clipboard) {
|
EsFileStore *EsClipboardOpen(EsClipboard clipboard) {
|
||||||
|
@ -773,7 +778,7 @@ EsFileStore *EsClipboardOpen(EsClipboard clipboard) {
|
||||||
return fileStore;
|
return fileStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format, EsFileStore *fileStore) {
|
EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format, EsFileStore *fileStore, uint32_t flags) {
|
||||||
(void) clipboard;
|
(void) clipboard;
|
||||||
EsError error = fileStore->error;
|
EsError error = fileStore->error;
|
||||||
|
|
||||||
|
@ -782,6 +787,7 @@ EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format,
|
||||||
information.desktopMessageTag = DESKTOP_MSG_CLIPBOARD_PUT;
|
information.desktopMessageTag = DESKTOP_MSG_CLIPBOARD_PUT;
|
||||||
information.error = error;
|
information.error = error;
|
||||||
information.format = format;
|
information.format = format;
|
||||||
|
information.flags = flags;
|
||||||
MessageDesktop(&information, sizeof(information));
|
MessageDesktop(&information, sizeof(information));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -828,7 +834,7 @@ bool EsClipboardHasData(EsClipboard clipboard) {
|
||||||
return information.error == ES_SUCCESS && information.format != ES_CLIPBOARD_FORMAT_INVALID;
|
return information.error == ES_SUCCESS && information.format != ES_CLIPBOARD_FORMAT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes) {
|
char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes, uint32_t *flags) {
|
||||||
(void) clipboard;
|
(void) clipboard;
|
||||||
|
|
||||||
char *result = nullptr;
|
char *result = nullptr;
|
||||||
|
@ -841,6 +847,10 @@ char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes) {
|
||||||
if (file) {
|
if (file) {
|
||||||
if (information.format == ES_CLIPBOARD_FORMAT_TEXT || information.format == ES_CLIPBOARD_FORMAT_PATH_LIST) {
|
if (information.format == ES_CLIPBOARD_FORMAT_TEXT || information.format == ES_CLIPBOARD_FORMAT_PATH_LIST) {
|
||||||
result = (char *) EsFileReadAllFromHandle(file, bytes);
|
result = (char *) EsFileReadAllFromHandle(file, bytes);
|
||||||
|
|
||||||
|
if (flags) {
|
||||||
|
*flags = information.flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EsHandleClose(file);
|
EsHandleClose(file);
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -60,6 +60,7 @@ DEFINE_INTERFACE_STRING(CommonListViewTypeTiles, "Tiles");
|
||||||
DEFINE_INTERFACE_STRING(CommonListViewTypeDetails, "Details");
|
DEFINE_INTERFACE_STRING(CommonListViewTypeDetails, "Details");
|
||||||
|
|
||||||
DEFINE_INTERFACE_STRING(CommonAnnouncementCopied, "Copied");
|
DEFINE_INTERFACE_STRING(CommonAnnouncementCopied, "Copied");
|
||||||
|
DEFINE_INTERFACE_STRING(CommonAnnouncementCut, "Cut");
|
||||||
DEFINE_INTERFACE_STRING(CommonAnnouncementTextCopied, "Text copied");
|
DEFINE_INTERFACE_STRING(CommonAnnouncementTextCopied, "Text copied");
|
||||||
DEFINE_INTERFACE_STRING(CommonAnnouncementCopyErrorResources, "There's not enough space to copy this");
|
DEFINE_INTERFACE_STRING(CommonAnnouncementCopyErrorResources, "There's not enough space to copy this");
|
||||||
DEFINE_INTERFACE_STRING(CommonAnnouncementCopyErrorOther, "Could not copy");
|
DEFINE_INTERFACE_STRING(CommonAnnouncementCopyErrorOther, "Could not copy");
|
||||||
|
|
|
@ -431,3 +431,4 @@ EsClipboardHasFormat=429
|
||||||
EsClipboardHasData=430
|
EsClipboardHasData=430
|
||||||
EsFileCopy=431
|
EsFileCopy=431
|
||||||
EsListViewSelectNone=432
|
EsListViewSelectNone=432
|
||||||
|
EsElementIsFocused=433
|
||||||
|
|
Loading…
Reference in New Issue