mirror of https://gitlab.com/nakst/essence
File Manager CommandCopy
This commit is contained in:
parent
77501bf37c
commit
d55a73dc5f
|
@ -1,4 +1,6 @@
|
|||
void CommandRename(Instance *instance, EsElement *, EsCommand *) {
|
||||
// TODO Undo.
|
||||
|
||||
intptr_t index = -1;
|
||||
|
||||
for (uintptr_t i = 0; i < instance->listContents.Length(); i++) {
|
||||
|
@ -117,6 +119,36 @@ void CommandNewFolder(Instance *instance, EsElement *, EsCommand *) {
|
|||
});
|
||||
}
|
||||
|
||||
void CommandCopy(Instance *instance, EsElement *, EsCommand *) {
|
||||
uint8_t _buffer[4096];
|
||||
EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) };
|
||||
buffer.fileStore = EsClipboardOpen(ES_CLIPBOARD_PRIMARY);
|
||||
|
||||
for (uintptr_t i = 0; i < instance->listContents.Length() && !buffer.error; i++) {
|
||||
if (instance->listContents[i].selected) {
|
||||
FolderEntry *entry = instance->listContents[i].entry;
|
||||
String name = entry->GetName();
|
||||
EsBufferWrite(&buffer, STRING(instance->path));
|
||||
EsBufferWrite(&buffer, STRING(name));
|
||||
uint8_t separator = '\n';
|
||||
EsBufferWrite(&buffer, &separator, 1);
|
||||
}
|
||||
}
|
||||
|
||||
EsBufferFlushToFileStore(&buffer);
|
||||
|
||||
EsPoint point = EsListViewGetAnnouncementPointForSelection(instance->list);
|
||||
EsError error = EsClipboardCloseAndAdd(ES_CLIPBOARD_PRIMARY, ES_CLIPBOARD_FORMAT_PATH_LIST, buffer.fileStore);
|
||||
|
||||
if (error == ES_SUCCESS) {
|
||||
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) {
|
||||
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementCopyErrorResources));
|
||||
} else {
|
||||
EsAnnouncementShow(instance->window, ES_FLAGS_DEFAULT, point.x, point.y, INTERFACE_STRING(CommonAnnouncementCopyErrorOther));
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceRegisterCommands(Instance *instance) {
|
||||
uint32_t stableCommandID = 1;
|
||||
|
||||
|
|
|
@ -168,7 +168,14 @@ void InstanceRefreshViewType(Instance *instance) {
|
|||
}
|
||||
|
||||
void InstanceUpdateItemSelectionCountCommands(Instance *instance) {
|
||||
EsCommandSetDisabled(&instance->commandRename, instance->selectedItemCount != 1 || !instance->folder->itemHandler->renameItem);
|
||||
EsCommandSetEnabled(&instance->commandRename, instance->selectedItemCount == 1 && instance->folder->itemHandler->renameItem);
|
||||
|
||||
#define COMMAND_SET(id, callback, enabled) \
|
||||
do { EsCommand *command = EsCommandByID(instance, id); \
|
||||
EsCommandSetEnabled(command, enabled); \
|
||||
EsCommandSetCallback(command, callback); } while(0)
|
||||
|
||||
COMMAND_SET(ES_COMMAND_COPY, CommandCopy, instance->selectedItemCount >= 1);
|
||||
}
|
||||
|
||||
int InstanceCompareFolderEntries(FolderEntry *left, FolderEntry *right, uint16_t sortColumn) {
|
||||
|
@ -688,7 +695,13 @@ int ListItemMessage(EsElement *element, EsMessage *message) {
|
|||
int ListCallback(EsElement *element, EsMessage *message) {
|
||||
Instance *instance = element->instance;
|
||||
|
||||
if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT) {
|
||||
if (message->type == ES_MSG_FOCUSED_START) {
|
||||
InstanceUpdateItemSelectionCountCommands(instance);
|
||||
return 0;
|
||||
} else if (message->type == ES_MSG_FOCUSED_END) {
|
||||
EsCommandSetCallback(EsCommandByID(instance, ES_COMMAND_COPY), nullptr);
|
||||
return 0;
|
||||
} else if (message->type == ES_MSG_LIST_VIEW_GET_CONTENT) {
|
||||
int column = message->getContent.column, index = message->getContent.index;
|
||||
EsAssert(index < (int) instance->listContents.Length() && index >= 0);
|
||||
ListEntry *listEntry = &instance->listContents[index];
|
||||
|
|
|
@ -178,8 +178,10 @@ int FontListMessage(EsElement *element, EsMessage *message) {
|
|||
font->categoryBytes, font->category, variants, variants == 1 ? "" : "s");
|
||||
EsTextDisplayCreate(row, ES_CELL_H_FILL | ES_CELL_V_BOTTOM, ES_STYLE_TEXT_LABEL_SECONDARY, description, descriptionBytes);
|
||||
|
||||
#if 0
|
||||
EsButton *openButton = EsButtonCreate(row, ES_BUTTON_NOT_FOCUSABLE);
|
||||
EsButtonSetIcon(openButton, ES_ICON_GO_NEXT_SYMBOLIC);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#define ES_DIRECT_API
|
||||
#include <essence.h>
|
||||
|
||||
extern "C" void EsUnimplemented();
|
||||
#define alloca __builtin_alloca
|
||||
#define FT_EXPORT(x) extern "C" x
|
||||
|
||||
|
@ -63,8 +62,6 @@ struct EnumString { const char *cName; int value; };
|
|||
#define DESKTOP_MSG_FILE_TYPES_GET (14)
|
||||
#define DESKTOP_MSG_UNHANDLED_KEY_EVENT (15)
|
||||
|
||||
extern "C" uintptr_t ProcessorTLSRead(uintptr_t offset);
|
||||
|
||||
struct EsFileStore {
|
||||
#define FILE_STORE_HANDLE (1)
|
||||
#define FILE_STORE_PATH (2)
|
||||
|
@ -110,8 +107,6 @@ struct Timer {
|
|||
EsGeneric argument;
|
||||
};
|
||||
|
||||
EsError NodeOpen(const char *path, size_t pathBytes, uint32_t flags, _EsNodeInformation *node);
|
||||
|
||||
struct {
|
||||
Array<EsSystemConfigurationGroup> systemConfigurationGroups;
|
||||
EsMutex systemConfigurationMutex;
|
||||
|
@ -142,9 +137,9 @@ struct {
|
|||
|
||||
ptrdiff_t tlsStorageOffset;
|
||||
|
||||
#include "syscall.cpp"
|
||||
|
||||
// Miscellanous forward declarations.
|
||||
extern "C" void EsUnimplemented();
|
||||
extern "C" uintptr_t ProcessorTLSRead(uintptr_t offset);
|
||||
void MaybeDestroyElement(EsElement *element);
|
||||
const char *GetConstantString(const char *key);
|
||||
void UndoManagerDestroy(EsUndoManager *manager);
|
||||
|
@ -153,6 +148,11 @@ struct APIInstance *InstanceSetup(EsInstance *instance);
|
|||
EsTextStyle TextPlanGetPrimaryStyle(EsTextPlan *plan);
|
||||
EsFileStore *FileStoreCreateFromEmbeddedFile(const char *path, size_t pathBytes);
|
||||
EsFileStore *FileStoreCreateFromPath(const char *path, size_t pathBytes);
|
||||
EsFileStore *FileStoreCreateFromHandle(EsHandle handle);
|
||||
void FileStoreCloseHandle(EsFileStore *fileStore);
|
||||
EsError NodeOpen(const char *path, size_t pathBytes, uint32_t flags, _EsNodeInformation *node);
|
||||
|
||||
#include "syscall.cpp"
|
||||
|
||||
struct ProcessMessageTiming {
|
||||
double startLogic, endLogic;
|
||||
|
@ -584,6 +584,15 @@ EsFileStore *FileStoreCreateFromPath(const char *path, size_t pathBytes) {
|
|||
return fileStore;
|
||||
}
|
||||
|
||||
EsFileStore *FileStoreCreateFromHandle(EsHandle handle) {
|
||||
EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore), true);
|
||||
fileStore->type = FILE_STORE_HANDLE;
|
||||
fileStore->handles = 1;
|
||||
fileStore->error = ES_SUCCESS;
|
||||
fileStore->handle = handle;
|
||||
return fileStore;
|
||||
}
|
||||
|
||||
EsFileStore *FileStoreCreateFromEmbeddedFile(const char *name, size_t nameBytes) {
|
||||
EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore) + nameBytes, false);
|
||||
EsMemoryZero(fileStore, sizeof(EsFileStore));
|
||||
|
@ -598,11 +607,7 @@ EsFileStore *FileStoreCreateFromEmbeddedFile(const char *name, size_t nameBytes)
|
|||
|
||||
void InstanceCreateFileStore(APIInstance *instance, EsHandle handle) {
|
||||
if (instance->fileStore) FileStoreCloseHandle(instance->fileStore);
|
||||
instance->fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore), true);
|
||||
instance->fileStore->type = FILE_STORE_HANDLE;
|
||||
instance->fileStore->handle = handle;
|
||||
instance->fileStore->error = ES_SUCCESS;
|
||||
instance->fileStore->handles = 1;
|
||||
instance->fileStore = FileStoreCreateFromHandle(handle);
|
||||
}
|
||||
|
||||
void InstancePostOpenMessage(EsInstance *_instance, bool update) {
|
||||
|
|
|
@ -644,7 +644,7 @@ struct EsListView : EsElement {
|
|||
position += visibleItem->element->width;
|
||||
} else if ((flags & ES_LIST_VIEW_COLUMNS) && ((~flags & ES_LIST_VIEW_CHOICE_SELECT) || (this->scroll.autoScrollbars[0]))) {
|
||||
int indent = visibleItem->indent * currentStyle->gapWrap;
|
||||
int firstColumn = columns[0].width + secondaryCellStyle->gapMajor;
|
||||
int firstColumn = columns[0].width * theming.scale + secondaryCellStyle->gapMajor;
|
||||
visibleItem->startAtSecondColumn = indent > firstColumn;
|
||||
if (indent > firstColumn) indent = firstColumn;
|
||||
visibleItem->element->InternalMove(totalColumnWidth - indent, visibleItem->size,
|
||||
|
@ -1134,7 +1134,7 @@ struct EsListView : EsElement {
|
|||
m.getContent.icon = 0;
|
||||
buffer.position = 0;
|
||||
|
||||
bounds.r = bounds.l + columns[i].width
|
||||
bounds.r = bounds.l + columns[i].width * theming.scale
|
||||
- element->currentStyle->insets.r - element->currentStyle->insets.l;
|
||||
|
||||
if (i == 0) {
|
||||
|
@ -1162,7 +1162,7 @@ struct EsListView : EsElement {
|
|||
style->textAlign = previousTextAlign;
|
||||
}
|
||||
|
||||
bounds.l += columns[i].width + secondaryCellStyle->gapMajor;
|
||||
bounds.l += columns[i].width * theming.scale + secondaryCellStyle->gapMajor;
|
||||
|
||||
if (i == 0) {
|
||||
bounds.l -= item->indent * currentStyle->gapWrap;
|
||||
|
@ -1545,7 +1545,7 @@ struct EsListView : EsElement {
|
|||
if (flags & ES_LIST_VIEW_COLUMNS) {
|
||||
int offset = primaryCellStyle->metrics->iconSize + primaryCellStyle->gapMinor
|
||||
+ style->insets.l - inlineTextbox->currentStyle->insets.l;
|
||||
inlineTextbox->InternalMove(columns[0].width - offset, item->element->height,
|
||||
inlineTextbox->InternalMove(columns[0].width * theming.scale - offset, item->element->height,
|
||||
item->element->offsetX + offset, item->element->offsetY);
|
||||
} else if (flags & ES_LIST_VIEW_TILED) {
|
||||
if (style->metrics->layoutVertical) {
|
||||
|
@ -1887,9 +1887,9 @@ void EsListViewChangeStyles(EsListView *view, const EsStyle *style, const EsStyl
|
|||
EsElement *item = element->children[i], *splitter = element->children[i + 1];
|
||||
EsListViewColumn *column = view->columns + item->userData.u;
|
||||
int splitterLeft = splitter->currentStyle->preferredWidth - view->secondaryCellStyle->gapMajor;
|
||||
item->InternalMove(column->width - splitterLeft, element->height, x, 0);
|
||||
splitter->InternalMove(splitter->currentStyle->preferredWidth, element->height, x + column->width - splitterLeft, 0);
|
||||
x += column->width + view->secondaryCellStyle->gapMajor;
|
||||
item->InternalMove(column->width * theming.scale - splitterLeft, element->height, x, 0);
|
||||
splitter->InternalMove(splitter->currentStyle->preferredWidth, element->height, x + column->width * theming.scale - splitterLeft, 0);
|
||||
x += column->width * theming.scale + view->secondaryCellStyle->gapMajor;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2199,6 +2199,14 @@ int ListViewColumnHeaderItemMessage(EsElement *element, EsMessage *message) {
|
|||
return ES_HANDLED;
|
||||
}
|
||||
|
||||
void ListViewCalculateTotalColumnWidth(EsListView *view) {
|
||||
view->totalColumnWidth = -view->secondaryCellStyle->gapMajor;
|
||||
|
||||
for (uintptr_t i = 0; i < view->columnCount; i++) {
|
||||
view->totalColumnWidth += view->columns[i].width * theming.scale + view->secondaryCellStyle->gapMajor;
|
||||
}
|
||||
}
|
||||
|
||||
void EsListViewSetColumns(EsListView *view, EsListViewColumn *columns, size_t columnCount) {
|
||||
EsMessageMutexCheck();
|
||||
|
||||
|
@ -2209,8 +2217,6 @@ void EsListViewSetColumns(EsListView *view, EsListViewColumn *columns, size_t co
|
|||
view->columns = columns;
|
||||
view->columnCount = columnCount;
|
||||
|
||||
view->totalColumnWidth = -view->secondaryCellStyle->gapMajor;
|
||||
|
||||
for (uintptr_t i = 0; i < columnCount; i++) {
|
||||
EsElement *columnHeaderItem = EsCustomElementCreate(view->columnHeader, ES_CELL_FILL,
|
||||
(columns[i].flags & ES_LIST_VIEW_COLUMN_HAS_MENU) ? ES_STYLE_LIST_COLUMN_HEADER_ITEM_HAS_MENU : ES_STYLE_LIST_COLUMN_HEADER_ITEM);
|
||||
|
@ -2220,7 +2226,7 @@ void EsListViewSetColumns(EsListView *view, EsListViewColumn *columns, size_t co
|
|||
columnHeaderItem->userData = i;
|
||||
|
||||
if (!columns[i].width) {
|
||||
columns[i].width = (i ? view->secondaryCellStyle : view->primaryCellStyle)->preferredWidth;
|
||||
columns[i].width = (i ? view->secondaryCellStyle : view->primaryCellStyle)->preferredWidth / theming.scale;
|
||||
}
|
||||
|
||||
EsElement *splitter = EsCustomElementCreate(view->columnHeader, ES_CELL_FILL, ES_STYLE_LIST_COLUMN_HEADER_SPLITTER);
|
||||
|
@ -2230,14 +2236,13 @@ void EsListViewSetColumns(EsListView *view, EsListViewColumn *columns, size_t co
|
|||
EsListView *view = (EsListView *) element->parent->parent;
|
||||
|
||||
if (message->type == ES_MSG_MOUSE_LEFT_DOWN) {
|
||||
view->columnResizingOriginalWidth = column->width;
|
||||
view->columnResizingOriginalWidth = column->width * theming.scale;
|
||||
} else if (message->type == ES_MSG_MOUSE_LEFT_DRAG) {
|
||||
int width = message->mouseDragged.newPositionX - message->mouseDragged.originalPositionX + view->columnResizingOriginalWidth;
|
||||
int minimumWidth = element->currentStyle->metrics->minimumWidth;
|
||||
if (width < minimumWidth) width = minimumWidth;
|
||||
|
||||
view->totalColumnWidth += width - column->width;
|
||||
column->width = width;
|
||||
column->width = width / theming.scale;
|
||||
ListViewCalculateTotalColumnWidth(view);
|
||||
EsElementRelayout(element->parent);
|
||||
EsElementRelayout(view);
|
||||
} else {
|
||||
|
@ -2249,10 +2254,9 @@ void EsListViewSetColumns(EsListView *view, EsListViewColumn *columns, size_t co
|
|||
|
||||
splitter->cName = "column header splitter";
|
||||
splitter->userData = columns + i;
|
||||
|
||||
view->totalColumnWidth += columns[i].width + view->secondaryCellStyle->gapMajor;
|
||||
}
|
||||
|
||||
ListViewCalculateTotalColumnWidth(view);
|
||||
view->scroll.Refresh();
|
||||
}
|
||||
|
||||
|
@ -2486,3 +2490,18 @@ void EsListViewEnumerateVisibleItems(EsListView *view, EsListViewEnumerateVisibl
|
|||
void EsListViewSetMaximumItemsPerBand(EsListView *view, int maximumItemsPerBand) {
|
||||
view->maximumItemsPerBand = maximumItemsPerBand;
|
||||
}
|
||||
|
||||
EsPoint EsListViewGetAnnouncementPointForSelection(EsListView *view) {
|
||||
EsRectangle bounding = EsElementGetWindowBounds(view);
|
||||
bool first = true;
|
||||
|
||||
for (uintptr_t i = 0; i < view->visibleItems.Length(); i++) {
|
||||
if (~view->visibleItems[i].element->customStyleState & THEME_STATE_SELECTED) continue;
|
||||
EsRectangle bounds = EsElementGetWindowBounds(view->visibleItems[i].element);
|
||||
if (first) bounding = bounds;
|
||||
else bounding = EsRectangleBounding(bounding, bounds);
|
||||
first = false;
|
||||
}
|
||||
|
||||
return ES_POINT((bounding.l + bounding.r) / 2, (bounding.t + bounding.b) / 2);
|
||||
}
|
||||
|
|
|
@ -1121,12 +1121,19 @@ enum EsDeviceType {
|
|||
ES_DEVICE_PCI_FUNCTION
|
||||
}
|
||||
|
||||
enum EsClipboardFormat {
|
||||
ES_CLIPBOARD_FORMAT_INVALID
|
||||
ES_CLIPBOARD_FORMAT_TEXT
|
||||
ES_CLIPBOARD_FORMAT_PATH_LIST
|
||||
}
|
||||
|
||||
function_pointer int EsUICallbackFunction(struct EsElement *element, struct EsMessage *message);
|
||||
|
||||
struct EsBuffer {
|
||||
union { const uint8_t *in; uint8_t *out; };
|
||||
size_t position, bytes;
|
||||
void *context;
|
||||
EsFileStore *fileStore;
|
||||
bool error, canGrow;
|
||||
};
|
||||
|
||||
|
@ -1382,7 +1389,7 @@ struct EsCommand {
|
|||
struct EsListViewColumn {
|
||||
STRING title;
|
||||
uint32_t flags;
|
||||
int width;
|
||||
double width;
|
||||
};
|
||||
|
||||
struct EsApplicationStartupInformation {
|
||||
|
@ -1936,6 +1943,7 @@ function bool EsPathQueryInformation(STRING filePath, EsDirectoryChild *informat
|
|||
|
||||
function void *EsFileStoreReadAll(EsFileStore *file, size_t *fileSize); // Free with EsHeapFree.
|
||||
function bool EsFileStoreWriteAll(EsFileStore *file, const void *data, size_t dataBytes);
|
||||
function bool EsFileStoreAppend(EsFileStore *file, const void *data, size_t dataBytes);
|
||||
function EsFileOffsetDifference EsFileStoreGetSize(EsFileStore *file); // Returns -1 on error.
|
||||
function void *EsFileStoreMap(EsFileStore *file, size_t *fileSize, uint32_t flags);
|
||||
|
||||
|
@ -1970,6 +1978,7 @@ function const void *EsBufferReadMany(struct EsBuffer *buffer, size_t a, size_t
|
|||
function void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writeBytes);
|
||||
function void EsBufferFormat(EsBuffer *buffer, EsCString format, ...); // Appends.
|
||||
function void EsBufferFormatV(EsBuffer *buffer, EsCString format, va_list arguments); // Appends.
|
||||
function void EsBufferFlushToFileStore(EsBuffer *buffer);
|
||||
|
||||
function EsHandle EsConstantBufferCreate(const void *data, size_t dataBytes, EsHandle targetProcess);
|
||||
function void EsConstantBufferRead(EsHandle constantBuffer, void *output);
|
||||
|
@ -2213,8 +2222,10 @@ function int EsCRTvsnprintf(char *buffer, size_t bufferSize, const char *format,
|
|||
// Clipboard and undo.
|
||||
|
||||
function EsError EsClipboardAddText(EsClipboard clipboard, STRING text = BLANK_STRING);
|
||||
function bool EsClipboardHasText(EsClipboard clipboard);
|
||||
function bool EsClipboardHasFormat(EsClipboard clipboard, EsClipboardFormat format);
|
||||
function char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes); // Free with EsHeapFree.
|
||||
function EsFileStore *EsClipboardOpen(EsClipboard clipboard); // Open the clipboard for writing.
|
||||
function EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format, EsFileStore *fileStore);
|
||||
|
||||
function void EsUndoClear(EsUndoManager *manager);
|
||||
function void EsUndoContinueGroup(EsUndoManager *manager);
|
||||
|
@ -2413,6 +2424,7 @@ function void EsListViewContentChanged(EsListView *view);
|
|||
function void EsListViewChangeStyles(EsListView *view, const EsStyle *style, const EsStyle *itemStyle,
|
||||
const EsStyle *headerItemStyle, const EsStyle *footerItemStyle, uint32_t addFlags, uint32_t removeFlags);
|
||||
function void EsListViewScrollToEnd(EsListView *view);
|
||||
function EsPoint EsListViewGetAnnouncementPointForSelection(EsListView *view);
|
||||
|
||||
function EsTextbox *EsListViewCreateInlineTextbox(EsListView *view, EsListViewIndex group, EsListViewIndex index, uint32_t flags = ES_FLAGS_DEFAULT);
|
||||
|
||||
|
|
|
@ -110,6 +110,9 @@ ES_EXTERN_C __attribute__((noreturn)) void _EsCRTlongjmp(EsCRTjmp_buf *env, int
|
|||
|
||||
#define EsWaitSingle(object) EsWait(&object, 1, ES_WAIT_NO_TIMEOUT)
|
||||
#define EsObjectUnmap EsMemoryUnreserve
|
||||
#define EsElementSetEnabled(element, enabled) EsElementSetDisabled(element, !(enabled))
|
||||
#define EsCommandSetEnabled(command, enabled) EsCommandSetDisabled(command, !(enabled))
|
||||
#define EsClipboardHasText(clipboard) EsClipboardHasFormat(clipboard, ES_CLIPBOARD_FORMAT_TEXT)
|
||||
|
||||
#define EsLiteral(x) (char *) x, EsCStringLength((char *) x)
|
||||
|
||||
|
|
|
@ -319,6 +319,19 @@ bool EsFileStoreWriteAll(EsFileStore *file, const void *data, size_t dataBytes)
|
|||
return file->error == ES_SUCCESS;
|
||||
}
|
||||
|
||||
bool EsFileStoreAppend(EsFileStore *file, const void *data, size_t dataBytes) {
|
||||
if (file->error == ES_SUCCESS) {
|
||||
if (file->type == FILE_STORE_HANDLE) {
|
||||
EsError error = EsFileWriteSync(file->handle, EsFileGetSize(file->handle), dataBytes, data);
|
||||
if (ES_CHECK_ERROR(error)) file->error = error;
|
||||
} else {
|
||||
EsAssert(false);
|
||||
}
|
||||
}
|
||||
|
||||
return file->error == ES_SUCCESS;
|
||||
}
|
||||
|
||||
EsFileOffsetDifference EsFileStoreGetSize(EsFileStore *file) {
|
||||
if (file->type == FILE_STORE_HANDLE) {
|
||||
return EsFileGetSize(file->handle);
|
||||
|
@ -691,10 +704,10 @@ void MessageDesktop(void *message, size_t messageBytes, EsHandle embeddedWindow
|
|||
struct ClipboardInformation {
|
||||
uint8_t desktopMessageTag;
|
||||
intptr_t error;
|
||||
bool isText;
|
||||
EsClipboardFormat format;
|
||||
};
|
||||
|
||||
EsError EsClipboardAddText(EsClipboard clipboard, const char *text, ptrdiff_t textBytes) {
|
||||
EsFileStore *EsClipboardOpen(EsClipboard clipboard) {
|
||||
(void) clipboard;
|
||||
uint8_t m = DESKTOP_MSG_CREATE_CLIPBOARD_FILE;
|
||||
EsBuffer buffer = { .canGrow = true };
|
||||
|
@ -704,17 +717,33 @@ EsError EsClipboardAddText(EsClipboard clipboard, const char *text, ptrdiff_t te
|
|||
EsBufferReadInto(&buffer, &file, sizeof(file));
|
||||
EsBufferReadInto(&buffer, &error, sizeof(error));
|
||||
EsHeapFree(buffer.out);
|
||||
if (error != ES_SUCCESS) return error;
|
||||
error = EsFileWriteAllFromHandle(file, text, textBytes);
|
||||
EsHandleClose(file);
|
||||
ClipboardInformation information = {};
|
||||
information.desktopMessageTag = DESKTOP_MSG_CLIPBOARD_PUT;
|
||||
information.error = error;
|
||||
information.isText = true;
|
||||
MessageDesktop(&information, sizeof(information));
|
||||
EsFileStore *fileStore = FileStoreCreateFromHandle(file);
|
||||
fileStore->error = error;
|
||||
return fileStore;
|
||||
}
|
||||
|
||||
EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format, EsFileStore *fileStore) {
|
||||
(void) clipboard;
|
||||
EsError error = fileStore->error;
|
||||
|
||||
if (error == ES_SUCCESS) {
|
||||
ClipboardInformation information = {};
|
||||
information.desktopMessageTag = DESKTOP_MSG_CLIPBOARD_PUT;
|
||||
information.error = error;
|
||||
information.format = format;
|
||||
MessageDesktop(&information, sizeof(information));
|
||||
}
|
||||
|
||||
FileStoreCloseHandle(fileStore);
|
||||
return error;
|
||||
}
|
||||
|
||||
EsError EsClipboardAddText(EsClipboard clipboard, const char *text, ptrdiff_t textBytes) {
|
||||
EsFileStore *fileStore = EsClipboardOpen(clipboard);
|
||||
EsFileStoreWriteAll(fileStore, text, textBytes);
|
||||
return EsClipboardCloseAndAdd(clipboard, ES_CLIPBOARD_FORMAT_TEXT, fileStore);
|
||||
}
|
||||
|
||||
void ClipboardGetInformation(EsHandle *file, ClipboardInformation *information) {
|
||||
uint8_t m = DESKTOP_MSG_CLIPBOARD_GET;
|
||||
EsBuffer buffer = { .canGrow = true };
|
||||
|
@ -724,13 +753,13 @@ void ClipboardGetInformation(EsHandle *file, ClipboardInformation *information)
|
|||
EsHeapFree(buffer.out);
|
||||
}
|
||||
|
||||
bool EsClipboardHasText(EsClipboard clipboard) {
|
||||
bool EsClipboardHasFormat(EsClipboard clipboard, EsClipboardFormat format) {
|
||||
(void) clipboard;
|
||||
EsHandle file;
|
||||
ClipboardInformation information;
|
||||
ClipboardGetInformation(&file, &information);
|
||||
if (file) EsHandleClose(file);
|
||||
return information.error == ES_SUCCESS && information.isText;
|
||||
return information.error == ES_SUCCESS && information.format == format;
|
||||
}
|
||||
|
||||
char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes) {
|
||||
|
@ -744,7 +773,7 @@ char *EsClipboardReadText(EsClipboard clipboard, size_t *bytes) {
|
|||
ClipboardGetInformation(&file, &information);
|
||||
|
||||
if (file) {
|
||||
if (information.isText) {
|
||||
if (information.format == ES_CLIPBOARD_FORMAT_TEXT) {
|
||||
result = (char *) EsFileReadAllFromHandle(file, bytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -3091,7 +3091,7 @@ void TextboxUpdateCommands(EsTextbox *textbox, bool noClipboard) {
|
|||
|
||||
if (error == ES_SUCCESS) {
|
||||
EsAnnouncementShow(textbox->window, ES_FLAGS_DEFAULT, x, y, INTERFACE_STRING(CommonAnnouncementTextCopied));
|
||||
} else if (error == ES_ERROR_INSUFFICIENT_RESOURCES) {
|
||||
} else if (error == ES_ERROR_INSUFFICIENT_RESOURCES || error == ES_ERROR_DRIVE_FULL) {
|
||||
EsAnnouncementShow(textbox->window, ES_FLAGS_DEFAULT, x, y, INTERFACE_STRING(CommonAnnouncementCopyErrorResources));
|
||||
} else {
|
||||
EsAnnouncementShow(textbox->window, ES_FLAGS_DEFAULT, x, y, INTERFACE_STRING(CommonAnnouncementCopyErrorOther));
|
||||
|
|
|
@ -787,7 +787,7 @@ void NVMeController::Initialise() {
|
|||
uint64_t sectorBytes = 1 << sectorBytesExponent;
|
||||
uint64_t capacity = *(uint64_t *) (identifyData + 4096 + 8) * sectorBytes;
|
||||
|
||||
bool readOnly = identifyData[99] & (1 << 0);
|
||||
bool readOnly = identifyData[4096 + 99] & (1 << 0);
|
||||
|
||||
KernelLog(LOG_INFO, "NVMe", "namespace identified", "Identifier namespace %d with sectors of size %D, and a capacity of %D.%z\n",
|
||||
nsid, sectorBytes, capacity, readOnly ? " The namespace is read-only." : "");
|
||||
|
|
|
@ -154,7 +154,7 @@ WindowManager windowManager;
|
|||
void SendMessageToWindow(Window *window, EsMessage *message);
|
||||
|
||||
#ifdef TEST_HIGH_UI_SCALE
|
||||
#define UI_SCALE (140)
|
||||
#define UI_SCALE TEST_HIGH_UI_SCALE
|
||||
#else
|
||||
#define UI_SCALE (100)
|
||||
#endif
|
||||
|
|
|
@ -2540,6 +2540,8 @@ const void *EsBufferRead(EsBuffer *buffer, size_t readBytes) {
|
|||
}
|
||||
|
||||
bool EsBufferReadInto(EsBuffer *buffer, void *destination, size_t readBytes) {
|
||||
// TODO Support buffered reading from a EsFileStore.
|
||||
|
||||
const void *source = EsBufferRead(buffer, readBytes);
|
||||
|
||||
if (source) {
|
||||
|
@ -2577,6 +2579,15 @@ uint32_t EsBufferReadInt(EsBuffer *buffer) {
|
|||
return p ? *p : 0;
|
||||
}
|
||||
|
||||
#ifdef ES_API
|
||||
void EsBufferFlushToFileStore(EsBuffer *buffer) {
|
||||
if (!buffer->position || buffer->error) return;
|
||||
EsAssert(buffer->fileStore && buffer->position <= buffer->bytes);
|
||||
buffer->error = !EsFileStoreAppend(buffer->fileStore, buffer->out, buffer->position);
|
||||
buffer->position = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writeBytes) {
|
||||
#ifdef ES_API
|
||||
tryAgain:;
|
||||
|
@ -2584,6 +2595,22 @@ void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writeBytes) {
|
|||
|
||||
if (buffer->error) {
|
||||
return NULL;
|
||||
#ifdef ES_API
|
||||
} else if (buffer->fileStore) {
|
||||
while (writeBytes && !buffer->error) {
|
||||
if (buffer->position == buffer->bytes) {
|
||||
EsBufferFlushToFileStore(buffer);
|
||||
} else {
|
||||
size_t bytesToWrite = writeBytes > buffer->bytes - buffer->position ? buffer->bytes - buffer->position : writeBytes;
|
||||
EsMemoryCopy(buffer->out + buffer->position, source, bytesToWrite);
|
||||
buffer->position += bytesToWrite;
|
||||
writeBytes -= bytesToWrite;
|
||||
source = (const uint8_t *) source + bytesToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (buffer->bytes - buffer->position < writeBytes) {
|
||||
#ifdef ES_API
|
||||
if (buffer->canGrow) {
|
||||
|
|
|
@ -59,6 +59,7 @@ DEFINE_INTERFACE_STRING(CommonListViewTypeThumbnails, "Thumbnails");
|
|||
DEFINE_INTERFACE_STRING(CommonListViewTypeTiles, "Tiles");
|
||||
DEFINE_INTERFACE_STRING(CommonListViewTypeDetails, "Details");
|
||||
|
||||
DEFINE_INTERFACE_STRING(CommonAnnouncementCopied, "Copied");
|
||||
DEFINE_INTERFACE_STRING(CommonAnnouncementTextCopied, "Text copied");
|
||||
DEFINE_INTERFACE_STRING(CommonAnnouncementCopyErrorResources, "There's not enough space to copy this");
|
||||
DEFINE_INTERFACE_STRING(CommonAnnouncementCopyErrorOther, "Could not copy");
|
||||
|
|
|
@ -35,6 +35,8 @@ EsMouseSetPosition=33
|
|||
EsPaintTargetClear=34
|
||||
EsCommandSetCheck=35
|
||||
EsTextboxGetContentsAsDouble=36
|
||||
EsFileStoreAppend=37
|
||||
EsBufferFlushToFileStore=38
|
||||
EsDirectoryEnumerateChildren=39
|
||||
EsPathExists=40
|
||||
EsInstanceSetClassViewer=41
|
||||
|
@ -233,7 +235,7 @@ EsMenuNextColumn=233
|
|||
EsMenuAddCommand=234
|
||||
EsMenuCloseAll=235
|
||||
EsUndoPush=236
|
||||
EsClipboardHasText=237
|
||||
EsListViewGetAnnouncementPointForSelection=237
|
||||
EsUndoInvokeGroup=238
|
||||
EsUndoEndGroup=239
|
||||
EsElementDraw=240
|
||||
|
@ -335,6 +337,7 @@ EsMenuCreate=335
|
|||
EsTextPlanReplaceStyleRenderProperties=336
|
||||
EsInstanceSetActiveUndoManager=337
|
||||
EsClipboardReadText=338
|
||||
EsClipboardOpen=339
|
||||
EsSpacerCreate=340
|
||||
EsTextPlanCreate=341
|
||||
EsStringEndsWith=342
|
||||
|
@ -418,8 +421,10 @@ EsFileStoreGetSize=419
|
|||
EsFileStoreMap=420
|
||||
EsTimerCancel=421
|
||||
EsSliderSetValue=422
|
||||
EsClipboardCloseAndAdd=423
|
||||
EsListViewFixedItemInsert=424
|
||||
EsListViewFixedItemAddString=425
|
||||
EsListViewFixedItemFindIndex=426
|
||||
EsListViewFixedItemSelect=427
|
||||
EsListViewFixedItemGetSelected=428
|
||||
EsClipboardHasFormat=429
|
||||
|
|
|
@ -282,7 +282,7 @@ Option options[] = {
|
|||
{ "Flag.USE_SMP", OPTION_TYPE_BOOL, { .b = true } },
|
||||
{ "Flag.BGA_RESOLUTION_WIDTH", OPTION_TYPE_STRING, { .s = "1600" } },
|
||||
{ "Flag.BGA_RESOLUTION_HEIGHT", OPTION_TYPE_STRING, { .s = "900" } },
|
||||
{ "Flag.TEST_HIGH_UI_SCALE", OPTION_TYPE_BOOL, { .b = false } },
|
||||
{ "Flag.TEST_HIGH_UI_SCALE", OPTION_TYPE_STRING, { .s = "100" } },
|
||||
{ "Flag.VGA_TEXT_MODE", OPTION_TYPE_BOOL, { .b = false } },
|
||||
{ "Flag.CHECK_FOR_NOT_RESPONDING", OPTION_TYPE_BOOL, { .b = true } },
|
||||
{ "Flag._ALWAYS_USE_VBE", OPTION_TYPE_BOOL, { .b = false } },
|
||||
|
|
Loading…
Reference in New Issue