mirror of https://gitlab.com/nakst/essence
basic file copy and paste
This commit is contained in:
parent
d55a73dc5f
commit
35d4f727f9
|
@ -120,6 +120,9 @@ void CommandNewFolder(Instance *instance, EsElement *, EsCommand *) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
||||||
|
// 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.
|
||||||
|
|
||||||
uint8_t _buffer[4096];
|
uint8_t _buffer[4096];
|
||||||
EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) };
|
EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) };
|
||||||
buffer.fileStore = EsClipboardOpen(ES_CLIPBOARD_PRIMARY);
|
buffer.fileStore = EsClipboardOpen(ES_CLIPBOARD_PRIMARY);
|
||||||
|
@ -127,9 +130,9 @@ void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
||||||
for (uintptr_t i = 0; i < instance->listContents.Length() && !buffer.error; i++) {
|
for (uintptr_t i = 0; i < instance->listContents.Length() && !buffer.error; i++) {
|
||||||
if (instance->listContents[i].selected) {
|
if (instance->listContents[i].selected) {
|
||||||
FolderEntry *entry = instance->listContents[i].entry;
|
FolderEntry *entry = instance->listContents[i].entry;
|
||||||
String name = entry->GetName();
|
String path = instance->folder->itemHandler->getPathForChild(instance->folder, entry);
|
||||||
EsBufferWrite(&buffer, STRING(instance->path));
|
EsBufferWrite(&buffer, STRING(path));
|
||||||
EsBufferWrite(&buffer, STRING(name));
|
StringDestroy(&path);
|
||||||
uint8_t separator = '\n';
|
uint8_t separator = '\n';
|
||||||
EsBufferWrite(&buffer, &separator, 1);
|
EsBufferWrite(&buffer, &separator, 1);
|
||||||
}
|
}
|
||||||
|
@ -149,6 +152,66 @@ void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandPaste(Instance *instance, EsElement *, EsCommand *) {
|
||||||
|
if (EsClipboardHasFormat(ES_CLIPBOARD_PRIMARY, ES_CLIPBOARD_FORMAT_PATH_LIST)) {
|
||||||
|
// TODO Background task.
|
||||||
|
// TODO Renaming.
|
||||||
|
// TODO Recursing into folders.
|
||||||
|
// TODO Reporting errors properly.
|
||||||
|
// TODO Other namespace handlers.
|
||||||
|
// TODO Selecting *all* pasted files.
|
||||||
|
// TODO Update parent folders after copy complete.
|
||||||
|
|
||||||
|
void *copyBuffer = nullptr;
|
||||||
|
|
||||||
|
size_t bytes;
|
||||||
|
char *pathList = EsClipboardReadText(ES_CLIPBOARD_PRIMARY, &bytes);
|
||||||
|
|
||||||
|
if (pathList) {
|
||||||
|
const char *position = pathList;
|
||||||
|
|
||||||
|
while (bytes) {
|
||||||
|
const char *newline = (const char *) EsCRTmemchr(position, '\n', bytes);
|
||||||
|
if (!newline) break;
|
||||||
|
|
||||||
|
String source = StringFromLiteralWithSize(position, newline - position);
|
||||||
|
String name = PathGetName(source);
|
||||||
|
String destination = StringAllocateAndFormat("%s%s", STRFMT(instance->folder->path), STRFMT(name));
|
||||||
|
EsError error = EsFileCopy(STRING(source), STRING(destination), ©Buffer);
|
||||||
|
|
||||||
|
if (error == ES_SUCCESS) {
|
||||||
|
EsMutexAcquire(&instance->folder->modifyEntriesMutex);
|
||||||
|
EsAssert(instance->folder->doneInitialEnumeration);
|
||||||
|
EsDirectoryChild directoryChild;
|
||||||
|
|
||||||
|
if (EsPathQueryInformation(STRING(destination), &directoryChild)) {
|
||||||
|
FolderAddEntryAndUpdateInstances(instance->folder, STRING(name), &directoryChild, instance);
|
||||||
|
} else {
|
||||||
|
// File must have been deleted by the time we got here!
|
||||||
|
}
|
||||||
|
|
||||||
|
EsMutexRelease(&instance->folder->modifyEntriesMutex);
|
||||||
|
} else {
|
||||||
|
goto encounteredError;
|
||||||
|
}
|
||||||
|
|
||||||
|
position += source.bytes + 1;
|
||||||
|
bytes -= source.bytes + 1;
|
||||||
|
StringDestroy(&destination);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
encounteredError:;
|
||||||
|
EsPoint point = EsListViewGetAnnouncementPointForSelection(instance->list);
|
||||||
|
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementPasteErrorOther));
|
||||||
|
}
|
||||||
|
|
||||||
|
EsHeapFree(pathList);
|
||||||
|
EsHeapFree(copyBuffer);
|
||||||
|
} else {
|
||||||
|
// TODO Paste the data into a new file.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void InstanceRegisterCommands(Instance *instance) {
|
void InstanceRegisterCommands(Instance *instance) {
|
||||||
uint32_t stableCommandID = 1;
|
uint32_t stableCommandID = 1;
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
|
|
||||||
Array<Folder *> loadedFolders;
|
Array<Folder *> loadedFolders;
|
||||||
|
|
||||||
// #define MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES (20)
|
#define MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES (20)
|
||||||
// TODO Temporary.
|
|
||||||
#define MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES (0)
|
|
||||||
Array<Folder *> foldersWithNoAttachedInstances;
|
Array<Folder *> foldersWithNoAttachedInstances;
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -57,7 +55,6 @@ EsError FSDirRenameItem(Folder *folder, String oldName, String newName) {
|
||||||
};
|
};
|
||||||
|
|
||||||
EsError FSDirEnumerate(Folder *folder) {
|
EsError FSDirEnumerate(Folder *folder) {
|
||||||
// Get the initial directory children.
|
|
||||||
// TODO Recurse mode.
|
// TODO Recurse mode.
|
||||||
|
|
||||||
EsNodeType type;
|
EsNodeType type;
|
||||||
|
@ -66,6 +63,13 @@ EsError FSDirEnumerate(Folder *folder) {
|
||||||
return ES_ERROR_FILE_DOES_NOT_EXIST;
|
return ES_ERROR_FILE_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EsVolumeInformation volume;
|
||||||
|
folder->readOnly = true;
|
||||||
|
|
||||||
|
if (EsMountPointGetVolumeInformation(STRING(folder->path), &volume)) {
|
||||||
|
folder->readOnly = volume.flags & ES_VOLUME_READ_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
EsDirectoryChild *buffer = nullptr;
|
EsDirectoryChild *buffer = nullptr;
|
||||||
ptrdiff_t _entryCount = EsDirectoryEnumerateChildren(STRING(folder->path), &buffer);
|
ptrdiff_t _entryCount = EsDirectoryEnumerateChildren(STRING(folder->path), &buffer);
|
||||||
|
|
||||||
|
@ -90,8 +94,9 @@ void FSDirGetTotalSize(Folder *folder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String FSDirGetPathForChildFolder(Folder *folder, String item) {
|
String FSDirGetPathForChild(Folder *folder, FolderEntry *entry) {
|
||||||
return StringAllocateAndFormat("%s%s/", STRFMT(folder->path), STRFMT(item));
|
String item = entry->GetInternalName();
|
||||||
|
return StringAllocateAndFormat("%s%s%z", STRFMT(folder->path), STRFMT(item), entry->isFolder ? "/" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -153,7 +158,8 @@ EsError DrivesPageEnumerate(Folder *folder) {
|
||||||
return ES_SUCCESS;
|
return ES_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
String DrivesPageGetPathForChildFolder(Folder *, String item) {
|
String DrivesPageGetPathForChild(Folder *, FolderEntry *entry) {
|
||||||
|
String item = entry->GetInternalName();
|
||||||
return StringAllocateAndFormat("%s/", STRFMT(item));
|
return StringAllocateAndFormat("%s/", STRFMT(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +203,7 @@ NamespaceHandler namespaceHandlers[] = {
|
||||||
.getFileType = DrivesPageGetFileType,
|
.getFileType = DrivesPageGetFileType,
|
||||||
.getVisibleName = DrivesPageGetVisibleName,
|
.getVisibleName = DrivesPageGetVisibleName,
|
||||||
.getTotalSize = DrivesPageGetTotalSize,
|
.getTotalSize = DrivesPageGetTotalSize,
|
||||||
.getPathForChildFolder = DrivesPageGetPathForChildFolder,
|
.getPathForChild = DrivesPageGetPathForChild,
|
||||||
.getDefaultViewSettings = DrivesPageGetDefaultViewSettings,
|
.getDefaultViewSettings = DrivesPageGetDefaultViewSettings,
|
||||||
.enumerate = DrivesPageEnumerate,
|
.enumerate = DrivesPageEnumerate,
|
||||||
},
|
},
|
||||||
|
@ -205,11 +211,13 @@ NamespaceHandler namespaceHandlers[] = {
|
||||||
{
|
{
|
||||||
.type = NAMESPACE_HANDLER_FILE_SYSTEM,
|
.type = NAMESPACE_HANDLER_FILE_SYSTEM,
|
||||||
.rootContainerHandlerType = NAMESPACE_HANDLER_DRIVES_PAGE,
|
.rootContainerHandlerType = NAMESPACE_HANDLER_DRIVES_PAGE,
|
||||||
|
.canCopy = true,
|
||||||
|
.canPaste = true,
|
||||||
.handlesPath = FSDirHandlesPath,
|
.handlesPath = FSDirHandlesPath,
|
||||||
.getFileType = NamespaceDefaultGetFileType,
|
.getFileType = NamespaceDefaultGetFileType,
|
||||||
.getVisibleName = NamespaceDefaultGetVisibleName,
|
.getVisibleName = NamespaceDefaultGetVisibleName,
|
||||||
.getTotalSize = FSDirGetTotalSize,
|
.getTotalSize = FSDirGetTotalSize,
|
||||||
.getPathForChildFolder = FSDirGetPathForChildFolder,
|
.getPathForChild = FSDirGetPathForChild,
|
||||||
.createChildFolder = FSDirCreateChildFolder,
|
.createChildFolder = FSDirCreateChildFolder,
|
||||||
.renameItem = FSDirRenameItem,
|
.renameItem = FSDirRenameItem,
|
||||||
.enumerate = FSDirEnumerate,
|
.enumerate = FSDirEnumerate,
|
||||||
|
|
|
@ -182,12 +182,14 @@ struct NamespaceHandler {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t rootContainerHandlerType;
|
uint8_t rootContainerHandlerType;
|
||||||
|
|
||||||
|
bool canCopy, canPaste;
|
||||||
|
|
||||||
bool (*handlesPath)(String path);
|
bool (*handlesPath)(String path);
|
||||||
|
|
||||||
uint32_t (*getFileType)(String path);
|
uint32_t (*getFileType)(String path);
|
||||||
void (*getVisibleName)(EsBuffer *buffer, String path);
|
void (*getVisibleName)(EsBuffer *buffer, String path);
|
||||||
void (*getTotalSize)(Folder *folder); // Possibly called on the blocking task thread.
|
void (*getTotalSize)(Folder *folder); // Possibly called on the blocking task thread.
|
||||||
String (*getPathForChildFolder)(Folder *folder, String item);
|
String (*getPathForChild)(Folder *folder, FolderEntry *entry);
|
||||||
void (*getDefaultViewSettings)(Folder *folder, FolderViewSettings *settings);
|
void (*getDefaultViewSettings)(Folder *folder, FolderViewSettings *settings);
|
||||||
|
|
||||||
// Called on the blocking task thread:
|
// Called on the blocking task thread:
|
||||||
|
@ -207,6 +209,7 @@ struct Folder {
|
||||||
bool recurse;
|
bool recurse;
|
||||||
bool refreshing;
|
bool refreshing;
|
||||||
bool driveRemoved;
|
bool driveRemoved;
|
||||||
|
bool readOnly;
|
||||||
|
|
||||||
bool doneInitialEnumeration;
|
bool doneInitialEnumeration;
|
||||||
EsMutex modifyEntriesMutex;
|
EsMutex modifyEntriesMutex;
|
||||||
|
|
|
@ -199,3 +199,10 @@ String PathRemoveTrailingSlash(String path) {
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String PathGetName(String path) {
|
||||||
|
intptr_t i = path.bytes - 2;
|
||||||
|
while (i >= 0 && path.text[i] != '/') i--;
|
||||||
|
path.text += i + 1, path.bytes -= i + 1;
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
|
@ -94,12 +94,12 @@ bool InstanceLoadFolder(Instance *instance, String path /* takes ownership */, i
|
||||||
|
|
||||||
// Update commands.
|
// Update commands.
|
||||||
|
|
||||||
EsCommandSetDisabled(&instance->commandGoBackwards, !instance->pathBackwardHistory.Length());
|
EsCommandSetEnabled(&instance->commandGoBackwards, instance->pathBackwardHistory.Length());
|
||||||
EsCommandSetDisabled(&instance->commandGoForwards, !instance->pathForwardHistory.Length());
|
EsCommandSetEnabled(&instance->commandGoForwards, instance->pathForwardHistory.Length());
|
||||||
EsCommandSetDisabled(&instance->commandGoParent, PathCountSections(folder->path) == 1);
|
EsCommandSetEnabled(&instance->commandGoParent, PathCountSections(folder->path) > 1);
|
||||||
EsCommandSetDisabled(&instance->commandNewFolder, !folder->itemHandler->createChildFolder);
|
EsCommandSetEnabled(&instance->commandNewFolder, folder->itemHandler->createChildFolder && !folder->readOnly);
|
||||||
EsCommandSetDisabled(&instance->commandRename, true);
|
EsCommandSetEnabled(&instance->commandRename, false);
|
||||||
EsCommandSetDisabled(&instance->commandRefresh, false);
|
EsCommandSetEnabled(&instance->commandRefresh, true);
|
||||||
|
|
||||||
// Load the view settings for the folder.
|
// Load the view settings for the folder.
|
||||||
|
|
||||||
|
@ -168,14 +168,15 @@ void InstanceRefreshViewType(Instance *instance) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceUpdateItemSelectionCountCommands(Instance *instance) {
|
void InstanceUpdateItemSelectionCountCommands(Instance *instance) {
|
||||||
EsCommandSetEnabled(&instance->commandRename, instance->selectedItemCount == 1 && instance->folder->itemHandler->renameItem);
|
EsCommandSetEnabled(&instance->commandRename, instance->selectedItemCount == 1 && instance->folder->itemHandler->renameItem && !instance->folder->readOnly);
|
||||||
|
|
||||||
#define COMMAND_SET(id, callback, enabled) \
|
#define COMMAND_SET(id, callback, enabled) \
|
||||||
do { EsCommand *command = EsCommandByID(instance, id); \
|
do { EsCommand *command = EsCommandByID(instance, id); \
|
||||||
EsCommandSetEnabled(command, enabled); \
|
EsCommandSetEnabled(command, enabled); \
|
||||||
EsCommandSetCallback(command, callback); } while(0)
|
EsCommandSetCallback(command, callback); } while(0)
|
||||||
|
|
||||||
COMMAND_SET(ES_COMMAND_COPY, CommandCopy, instance->selectedItemCount >= 1);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
int InstanceCompareFolderEntries(FolderEntry *left, FolderEntry *right, uint16_t sortColumn) {
|
int InstanceCompareFolderEntries(FolderEntry *left, FolderEntry *right, uint16_t sortColumn) {
|
||||||
|
@ -758,7 +759,7 @@ int ListCallback(EsElement *element, EsMessage *message) {
|
||||||
FolderEntry *entry = listEntry->entry;
|
FolderEntry *entry = listEntry->entry;
|
||||||
|
|
||||||
if (entry->isFolder) {
|
if (entry->isFolder) {
|
||||||
String path = instance->folder->itemHandler->getPathForChildFolder(instance->folder, entry->GetInternalName());
|
String path = instance->folder->itemHandler->getPathForChild(instance->folder, entry);
|
||||||
InstanceLoadFolder(instance, path);
|
InstanceLoadFolder(instance, path);
|
||||||
} else {
|
} else {
|
||||||
FileType *fileType = FolderEntryGetType(instance->folder, entry);
|
FileType *fileType = FolderEntryGetType(instance->folder, entry);
|
||||||
|
|
|
@ -168,6 +168,10 @@ void InitialiseInstance(EsInstance *instance) {
|
||||||
EsSyscall(ES_SYSCALL_WAIT, 0x00000FFFFFFFFFFF, 1, 0, 0);
|
EsSyscall(ES_SYSCALL_WAIT, 0x00000FFFFFFFFFFF, 1, 0, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Crash 6"), [] (EsInstance *, EsElement *, EsCommand *) {
|
||||||
|
EsMemoryCopy(nullptr, nullptr, 1);
|
||||||
|
});
|
||||||
|
|
||||||
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Announcement 1"), [] (EsInstance *, EsElement *element, EsCommand *) {
|
EsButtonOnCommand(EsButtonCreate(panel, ES_FLAGS_DEFAULT, 0, "Announcement 1"), [] (EsInstance *, EsElement *element, EsCommand *) {
|
||||||
EsRectangle bounds = EsElementGetWindowBounds(element);
|
EsRectangle bounds = EsElementGetWindowBounds(element);
|
||||||
EsAnnouncementShow(element->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, (bounds.t + bounds.b) / 2, "Hello, world!", -1);
|
EsAnnouncementShow(element->window, ES_FLAGS_DEFAULT, (bounds.l + bounds.r) / 2, (bounds.t + bounds.b) / 2, "Hello, world!", -1);
|
||||||
|
|
|
@ -1692,6 +1692,8 @@ struct EsListView : EsElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
EsCommandSetCallback(EsCommandByID(instance, ES_COMMAND_SELECT_ALL), nullptr);
|
EsCommandSetCallback(EsCommandByID(instance, ES_COMMAND_SELECT_ALL), nullptr);
|
||||||
|
} else if (message->type == ES_MSG_MOUSE_RIGHT_DOWN) {
|
||||||
|
// Make sure that right clicking will focus the list.
|
||||||
} else if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
|
} else if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
|
||||||
Select(-1, 0, EsKeyboardIsShiftHeld(), EsKeyboardIsCtrlHeld(), false);
|
Select(-1, 0, EsKeyboardIsShiftHeld(), EsKeyboardIsCtrlHeld(), false);
|
||||||
} else if (message->type == ES_MSG_MOUSE_LEFT_DRAG) {
|
} else if (message->type == ES_MSG_MOUSE_LEFT_DRAG) {
|
||||||
|
|
|
@ -725,6 +725,8 @@ define ES_DRAW_BITMAP_OPAQUE (0xFFFF)
|
||||||
define ES_DRAW_BITMAP_XOR (0xFFFE)
|
define ES_DRAW_BITMAP_XOR (0xFFFE)
|
||||||
define ES_DRAW_BITMAP_BLEND (0)
|
define ES_DRAW_BITMAP_BLEND (0)
|
||||||
|
|
||||||
|
define ES_VOLUME_READ_ONLY (1 << 0)
|
||||||
|
|
||||||
include desktop/icons.header
|
include desktop/icons.header
|
||||||
|
|
||||||
enum EsFatalError {
|
enum EsFatalError {
|
||||||
|
@ -1497,6 +1499,7 @@ struct EsVolumeInformation {
|
||||||
char label[64];
|
char label[64];
|
||||||
uint8_t labelBytes;
|
uint8_t labelBytes;
|
||||||
uint8_t driveType;
|
uint8_t driveType;
|
||||||
|
uint32_t flags;
|
||||||
EsObjectID id;
|
EsObjectID id;
|
||||||
EsFileOffset spaceTotal;
|
EsFileOffset spaceTotal;
|
||||||
EsFileOffset spaceUsed;
|
EsFileOffset spaceUsed;
|
||||||
|
@ -1925,6 +1928,7 @@ function EsError EsFileWriteAllFromHandle(EsHandle handle, const void *data, siz
|
||||||
function EsError EsFileWriteAllGather(STRING filePath, const void **data, size_t *fileSize, size_t gatherCount);
|
function EsError EsFileWriteAllGather(STRING filePath, const void **data, size_t *fileSize, size_t gatherCount);
|
||||||
function EsError EsFileWriteAllGatherFromHandle(EsHandle handle, const void **data, size_t *fileSize, size_t gatherCount);
|
function EsError EsFileWriteAllGatherFromHandle(EsHandle handle, const void **data, size_t *fileSize, size_t gatherCount);
|
||||||
function void *EsFileMap(STRING filePath, size_t *fileSize, uint32_t flags);
|
function void *EsFileMap(STRING filePath, size_t *fileSize, uint32_t flags);
|
||||||
|
function EsError EsFileCopy(STRING source, STRING destination, void **copyBuffer); // If you are copying lots of files, you can reuse the temporary copy buffer by storing the output copyBuffer; call EsHeapFree on it after the last copy.
|
||||||
|
|
||||||
function EsError EsFileControl(EsHandle file, uint32_t flags);
|
function EsError EsFileControl(EsHandle file, uint32_t flags);
|
||||||
function EsFileInformation EsFileOpen(STRING path, uint32_t flags);
|
function EsFileInformation EsFileOpen(STRING path, uint32_t flags);
|
||||||
|
@ -2223,6 +2227,7 @@ 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 char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes); // Free with EsHeapFree.
|
function char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes); // 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);
|
||||||
|
|
|
@ -223,6 +223,41 @@ void *EsFileReadAll(const char *filePath, ptrdiff_t filePathLength, size_t *file
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EsError EsFileCopy(const char *source, ptrdiff_t sourceBytes, const char *destination, ptrdiff_t destinationBytes, void **_copyBuffer) {
|
||||||
|
const size_t copyBufferBytes = 262144;
|
||||||
|
void *copyBuffer = _copyBuffer && *_copyBuffer ? *_copyBuffer : EsHeapAllocate(copyBufferBytes, false);
|
||||||
|
if (_copyBuffer) *_copyBuffer = copyBuffer;
|
||||||
|
|
||||||
|
if (!copyBuffer) {
|
||||||
|
return ES_ERROR_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
EsError error = ES_SUCCESS;
|
||||||
|
|
||||||
|
EsFileInformation sourceFile = EsFileOpen(source, sourceBytes, ES_FILE_READ | ES_NODE_FILE | ES_NODE_FAIL_IF_NOT_FOUND);
|
||||||
|
EsFileInformation destinationFile = EsFileOpen(destination, destinationBytes, ES_FILE_WRITE_EXCLUSIVE | ES_NODE_FILE | ES_NODE_FAIL_IF_FOUND);
|
||||||
|
|
||||||
|
if (sourceFile.error == ES_SUCCESS && destinationFile.error == ES_SUCCESS) {
|
||||||
|
error = EsFileResize(destinationFile.handle, sourceFile.size);
|
||||||
|
|
||||||
|
if (error == ES_SUCCESS) {
|
||||||
|
for (uintptr_t i = 0; i < sourceFile.size; i += copyBufferBytes) {
|
||||||
|
size_t bytesRead = EsFileReadSync(sourceFile.handle, i, copyBufferBytes, copyBuffer);
|
||||||
|
if (ES_CHECK_ERROR(bytesRead)) { error = bytesRead; break; }
|
||||||
|
size_t bytesWritten = EsFileWriteSync(destinationFile.handle, i, bytesRead, copyBuffer);
|
||||||
|
if (ES_CHECK_ERROR(bytesWritten)) { error = bytesWritten; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error = sourceFile.error == ES_SUCCESS ? destinationFile.error : sourceFile.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceFile.error == ES_SUCCESS) EsHandleClose(sourceFile.handle);
|
||||||
|
if (destinationFile.error == ES_SUCCESS) EsHandleClose(destinationFile.handle);
|
||||||
|
if (!_copyBuffer) EsHeapFree(copyBuffer);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
EsHandle EsMemoryOpen(size_t size, const char *name, ptrdiff_t nameLength, unsigned flags) {
|
EsHandle EsMemoryOpen(size_t size, const char *name, ptrdiff_t nameLength, unsigned flags) {
|
||||||
if (nameLength == -1) nameLength = EsCStringLength(name);
|
if (nameLength == -1) nameLength = EsCStringLength(name);
|
||||||
return EsSyscall(ES_SYSCALL_MEMORY_OPEN, size, (uintptr_t) name, nameLength, flags);
|
return EsSyscall(ES_SYSCALL_MEMORY_OPEN, size, (uintptr_t) name, nameLength, flags);
|
||||||
|
@ -759,7 +794,22 @@ bool EsClipboardHasFormat(EsClipboard clipboard, EsClipboardFormat format) {
|
||||||
ClipboardInformation information;
|
ClipboardInformation information;
|
||||||
ClipboardGetInformation(&file, &information);
|
ClipboardGetInformation(&file, &information);
|
||||||
if (file) EsHandleClose(file);
|
if (file) EsHandleClose(file);
|
||||||
return information.error == ES_SUCCESS && information.format == format;
|
if (information.error != ES_SUCCESS) return false;
|
||||||
|
|
||||||
|
if (format == ES_CLIPBOARD_FORMAT_TEXT) {
|
||||||
|
return information.format == ES_CLIPBOARD_FORMAT_TEXT || information.format == ES_CLIPBOARD_FORMAT_PATH_LIST;
|
||||||
|
} else {
|
||||||
|
return information.format == format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EsClipboardHasData(EsClipboard clipboard) {
|
||||||
|
(void) clipboard;
|
||||||
|
EsHandle file;
|
||||||
|
ClipboardInformation information;
|
||||||
|
ClipboardGetInformation(&file, &information);
|
||||||
|
if (file) EsHandleClose(file);
|
||||||
|
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) {
|
||||||
|
@ -773,7 +823,7 @@ char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes) {
|
||||||
ClipboardGetInformation(&file, &information);
|
ClipboardGetInformation(&file, &information);
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
if (information.format == ES_CLIPBOARD_FORMAT_TEXT) {
|
if (information.format == ES_CLIPBOARD_FORMAT_TEXT || information.format == ES_CLIPBOARD_FORMAT_PATH_LIST) {
|
||||||
result = (char *) EsFileReadAllFromHandle(file, bytes);
|
result = (char *) EsFileReadAllFromHandle(file, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,8 +214,6 @@ bool AHCIController::Access(uintptr_t portIndex, uint64_t offsetBytes, size_t co
|
||||||
AHCIPort *port = ports + portIndex;
|
AHCIPort *port = ports + portIndex;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// TODO Temporary.
|
|
||||||
|
|
||||||
if (operation == K_ACCESS_WRITE) {
|
if (operation == K_ACCESS_WRITE) {
|
||||||
KernelPanic("AHCIController::Access - Attempted write.\n");
|
KernelPanic("AHCIController::Access - Attempted write.\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -293,7 +293,6 @@ bool NVMeController::IssueAdminCommand(const void *command, uint32_t *result) {
|
||||||
|
|
||||||
bool NVMeController::Access(struct NVMeDrive *drive, uint64_t offsetBytes, size_t countBytes, int operation,
|
bool NVMeController::Access(struct NVMeDrive *drive, uint64_t offsetBytes, size_t countBytes, int operation,
|
||||||
KDMABuffer *buffer, uint64_t, KWorkGroup *dispatchGroup) {
|
KDMABuffer *buffer, uint64_t, KWorkGroup *dispatchGroup) {
|
||||||
// TODO Temporary.
|
|
||||||
// if (operation == K_ACCESS_WRITE) KernelPanic("NVMeController::Access - Attempted write.\n");
|
// if (operation == K_ACCESS_WRITE) KernelPanic("NVMeController::Access - Attempted write.\n");
|
||||||
|
|
||||||
// Build the PRPs.
|
// Build the PRPs.
|
||||||
|
|
|
@ -794,6 +794,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_VOLUME_GET_INFORMATION) {
|
||||||
information.spaceUsed = fileSystem->spaceUsed;
|
information.spaceUsed = fileSystem->spaceUsed;
|
||||||
information.spaceTotal = fileSystem->spaceTotal;
|
information.spaceTotal = fileSystem->spaceTotal;
|
||||||
information.id = fileSystem->objectID;
|
information.id = fileSystem->objectID;
|
||||||
|
information.flags = fileSystem->write ? ES_FLAGS_DEFAULT : ES_VOLUME_READ_ONLY;
|
||||||
|
|
||||||
SYSCALL_WRITE(argument1, &information, sizeof(EsVolumeInformation));
|
SYSCALL_WRITE(argument1, &information, sizeof(EsVolumeInformation));
|
||||||
SYSCALL_RETURN(ES_SUCCESS, false);
|
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||||
|
|
|
@ -939,27 +939,22 @@ extern "C" void InterruptHandler(InterruptContext *context) {
|
||||||
currentThread->process->cExecutableName,
|
currentThread->process->cExecutableName,
|
||||||
context->rip, local->processorID, context->rsp, context->errorCode, context->cr2);
|
context->rip, local->processorID, context->rsp, context->errorCode, context->cr2);
|
||||||
|
|
||||||
#ifndef __OPTIMIZE__
|
|
||||||
EsPrint("Attempting to make a stack trace...\n");
|
EsPrint("Attempting to make a stack trace...\n");
|
||||||
|
|
||||||
{
|
{
|
||||||
// TODO Temporary, may crash kernel.
|
uint64_t rbp = context->rbp;
|
||||||
// Attempt to make a stack trace.
|
int traceDepth = 0;
|
||||||
|
|
||||||
uint64_t *rbp = (uint64_t *) context->rbp;
|
while (rbp && traceDepth < 32) {
|
||||||
int i = 0;
|
uint64_t value;
|
||||||
|
if (!MMArchSafeCopy((uintptr_t) &value, rbp + 8, sizeof(uint64_t))) break;
|
||||||
while (rbp && i < 32) {
|
EsPrint("\t%d: %x\n", ++traceDepth, value);
|
||||||
EsPrint("\t%d: %x\n", ++i, rbp[1]);
|
if (!value) break;
|
||||||
if (!rbp[1]) break;
|
if (!MMArchSafeCopy((uintptr_t) &rbp, rbp, sizeof(uint64_t))) break;
|
||||||
rbp = (uint64_t *) (rbp[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EsPrint("Stack trace complete.\n");
|
EsPrint("Stack trace complete.\n");
|
||||||
#else
|
|
||||||
EsPrint("Disable optimisations to get a stack trace.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EsCrashReason crashReason;
|
EsCrashReason crashReason;
|
||||||
EsMemoryZero(&crashReason, sizeof(EsCrashReason));
|
EsMemoryZero(&crashReason, sizeof(EsCrashReason));
|
||||||
|
|
|
@ -63,6 +63,7 @@ DEFINE_INTERFACE_STRING(CommonAnnouncementCopied, "Copied");
|
||||||
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");
|
||||||
|
DEFINE_INTERFACE_STRING(CommonAnnouncementPasteErrorOther, "Could not paste");
|
||||||
|
|
||||||
DEFINE_INTERFACE_STRING(CommonEmpty, "empty");
|
DEFINE_INTERFACE_STRING(CommonEmpty, "empty");
|
||||||
|
|
||||||
|
|
|
@ -428,3 +428,5 @@ EsListViewFixedItemFindIndex=426
|
||||||
EsListViewFixedItemSelect=427
|
EsListViewFixedItemSelect=427
|
||||||
EsListViewFixedItemGetSelected=428
|
EsListViewFixedItemGetSelected=428
|
||||||
EsClipboardHasFormat=429
|
EsClipboardHasFormat=429
|
||||||
|
EsClipboardHasData=430
|
||||||
|
EsFileCopy=431
|
||||||
|
|
Loading…
Reference in New Issue