low memory fixes

This commit is contained in:
nakst 2021-09-07 11:18:03 +01:00
parent 0c50335c62
commit 10b259ca66
16 changed files with 380 additions and 159 deletions

View File

@ -287,14 +287,20 @@ EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup
if (createIfNeeded) { if (createIfNeeded) {
EsSystemConfigurationItem item = {}; EsSystemConfigurationItem item = {};
item.key = (char *) EsHeapAllocate(keyBytes, false); item.key = (char *) EsHeapAllocate(keyBytes, false);
if (!item.key) return nullptr;
item.keyBytes = keyBytes; item.keyBytes = keyBytes;
EsMemoryCopy(item.key, key, keyBytes); EsMemoryCopy(item.key, key, keyBytes);
Array<EsSystemConfigurationItem> items = { group->items }; Array<EsSystemConfigurationItem> items = { group->items };
EsSystemConfigurationItem *_item = items.Add(item); EsSystemConfigurationItem *_item = items.Add(item);
group->items = items.array; group->items = items.array;
group->itemCount++;
return _item; if (_item) {
group->itemCount++;
return _item;
} else {
EsHeapFree(item.key);
}
} }
return nullptr; return nullptr;
@ -312,9 +318,16 @@ EsSystemConfigurationGroup *SystemConfigurationGetGroup(const char *section, ptr
if (createIfNeeded) { if (createIfNeeded) {
EsSystemConfigurationGroup group = {}; EsSystemConfigurationGroup group = {};
group.section = (char *) EsHeapAllocate(sectionBytes, false); group.section = (char *) EsHeapAllocate(sectionBytes, false);
if (!group.section) return nullptr;
group.sectionBytes = sectionBytes; group.sectionBytes = sectionBytes;
EsMemoryCopy(group.section, section, sectionBytes); EsMemoryCopy(group.section, section, sectionBytes);
return api.systemConfigurationGroups.Add(group); EsSystemConfigurationGroup *_group = api.systemConfigurationGroups.Add(group);
if (_group) {
return _group;
} else {
EsHeapFree(group.section);
}
} }
return nullptr; return nullptr;
@ -325,6 +338,7 @@ char *EsSystemConfigurationGroupReadString(EsSystemConfigurationGroup *group, co
if (!item) { if (valueBytes) *valueBytes = 0; return nullptr; } if (!item) { if (valueBytes) *valueBytes = 0; return nullptr; }
if (valueBytes) *valueBytes = item->valueBytes; if (valueBytes) *valueBytes = item->valueBytes;
char *copy = (char *) EsHeapAllocate(item->valueBytes + 1, false); char *copy = (char *) EsHeapAllocate(item->valueBytes + 1, false);
if (!copy) { if (valueBytes) *valueBytes = 0; return nullptr; }
copy[item->valueBytes] = 0; copy[item->valueBytes] = 0;
EsMemoryCopy(copy, item->value, item->valueBytes); EsMemoryCopy(copy, item->value, item->valueBytes);
return copy; return copy;
@ -541,22 +555,28 @@ void _EsPathAnnouncePathMoved(const char *oldPath, ptrdiff_t oldPathBytes, const
if (newPathBytes == -1) newPathBytes = EsCStringLength(newPath); if (newPathBytes == -1) newPathBytes = EsCStringLength(newPath);
size_t bufferBytes = 1 + sizeof(uintptr_t) * 2 + oldPathBytes + newPathBytes; size_t bufferBytes = 1 + sizeof(uintptr_t) * 2 + oldPathBytes + newPathBytes;
char *buffer = (char *) EsHeapAllocate(bufferBytes, false); char *buffer = (char *) EsHeapAllocate(bufferBytes, false);
buffer[0] = DESKTOP_MSG_ANNOUNCE_PATH_MOVED;
EsMemoryCopy(buffer + 1, &oldPathBytes, sizeof(uintptr_t)); if (buffer) {
EsMemoryCopy(buffer + 1 + sizeof(uintptr_t), &newPathBytes, sizeof(uintptr_t)); buffer[0] = DESKTOP_MSG_ANNOUNCE_PATH_MOVED;
EsMemoryCopy(buffer + 1 + sizeof(uintptr_t) * 2, oldPath, oldPathBytes); EsMemoryCopy(buffer + 1, &oldPathBytes, sizeof(uintptr_t));
EsMemoryCopy(buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes, newPath, newPathBytes); EsMemoryCopy(buffer + 1 + sizeof(uintptr_t), &newPathBytes, sizeof(uintptr_t));
MessageDesktop(buffer, bufferBytes); EsMemoryCopy(buffer + 1 + sizeof(uintptr_t) * 2, oldPath, oldPathBytes);
EsHeapFree(buffer); EsMemoryCopy(buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes, newPath, newPathBytes);
MessageDesktop(buffer, bufferBytes);
EsHeapFree(buffer);
}
} }
void EsApplicationRunTemporary(EsInstance *instance, const char *path, ptrdiff_t pathBytes) { void EsApplicationRunTemporary(EsInstance *instance, const char *path, ptrdiff_t pathBytes) {
if (pathBytes == -1) pathBytes = EsCStringLength(path); if (pathBytes == -1) pathBytes = EsCStringLength(path);
char *buffer = (char *) EsHeapAllocate(pathBytes + 1, false); char *buffer = (char *) EsHeapAllocate(pathBytes + 1, false);
buffer[0] = DESKTOP_MSG_RUN_TEMPORARY_APPLICATION;
EsMemoryCopy(buffer + 1, path, pathBytes); if (buffer) {
MessageDesktop(buffer, pathBytes + 1, instance->window->handle); buffer[0] = DESKTOP_MSG_RUN_TEMPORARY_APPLICATION;
EsHeapFree(buffer); EsMemoryCopy(buffer + 1, path, pathBytes);
MessageDesktop(buffer, pathBytes + 1, instance->window->handle);
EsHeapFree(buffer);
}
} }
void EsSystemShowShutdownDialog() { void EsSystemShowShutdownDialog() {
@ -574,10 +594,13 @@ void InstanceSave(EsInstance *_instance) {
EsAssert(instance->instanceClass == ES_INSTANCE_CLASS_EDITOR); EsAssert(instance->instanceClass == ES_INSTANCE_CLASS_EDITOR);
size_t bufferBytes = instance->editorSettings.newDocumentFileNameBytes + 1; size_t bufferBytes = instance->editorSettings.newDocumentFileNameBytes + 1;
char *buffer = (char *) EsHeapAllocate(bufferBytes, false); char *buffer = (char *) EsHeapAllocate(bufferBytes, false);
buffer[0] = DESKTOP_MSG_REQUEST_SAVE;
EsMemoryCopy(buffer + 1, instance->editorSettings.newDocumentFileName, instance->editorSettings.newDocumentFileNameBytes); if (buffer) {
MessageDesktop(buffer, bufferBytes, _instance->window->handle); buffer[0] = DESKTOP_MSG_REQUEST_SAVE;
EsHeapFree(buffer); EsMemoryCopy(buffer + 1, instance->editorSettings.newDocumentFileName, instance->editorSettings.newDocumentFileNameBytes);
MessageDesktop(buffer, bufferBytes, _instance->window->handle);
EsHeapFree(buffer);
}
} }
void FileStoreCloseHandle(EsFileStore *fileStore) { void FileStoreCloseHandle(EsFileStore *fileStore) {
@ -601,6 +624,7 @@ void FileStoreCloseHandle(EsFileStore *fileStore) {
EsFileStore *FileStoreCreateFromPath(const char *path, size_t pathBytes) { EsFileStore *FileStoreCreateFromPath(const char *path, size_t pathBytes) {
EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore) + pathBytes, false); EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore) + pathBytes, false);
if (!fileStore) return nullptr;
EsMemoryZero(fileStore, sizeof(EsFileStore)); EsMemoryZero(fileStore, sizeof(EsFileStore));
fileStore->type = FILE_STORE_PATH; fileStore->type = FILE_STORE_PATH;
fileStore->handles = 1; fileStore->handles = 1;
@ -613,6 +637,7 @@ EsFileStore *FileStoreCreateFromPath(const char *path, size_t pathBytes) {
EsFileStore *FileStoreCreateFromHandle(EsHandle handle) { EsFileStore *FileStoreCreateFromHandle(EsHandle handle) {
EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore), true); EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore), true);
if (!fileStore) return nullptr;
fileStore->type = FILE_STORE_HANDLE; fileStore->type = FILE_STORE_HANDLE;
fileStore->handles = 1; fileStore->handles = 1;
fileStore->error = ES_SUCCESS; fileStore->error = ES_SUCCESS;
@ -622,6 +647,7 @@ EsFileStore *FileStoreCreateFromHandle(EsHandle handle) {
EsFileStore *FileStoreCreateFromEmbeddedFile(const char *name, size_t nameBytes) { EsFileStore *FileStoreCreateFromEmbeddedFile(const char *name, size_t nameBytes) {
EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore) + nameBytes, false); EsFileStore *fileStore = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore) + nameBytes, false);
if (!fileStore) return nullptr;
EsMemoryZero(fileStore, sizeof(EsFileStore)); EsMemoryZero(fileStore, sizeof(EsFileStore));
fileStore->type = FILE_STORE_EMBEDDED_FILE; fileStore->type = FILE_STORE_EMBEDDED_FILE;
fileStore->handles = 1; fileStore->handles = 1;
@ -919,35 +945,44 @@ EsMessage *EsMessageReceive() {
} else if (type == ES_MSG_INSTANCE_SAVE_RESPONSE) { } else if (type == ES_MSG_INSTANCE_SAVE_RESPONSE) {
EsMessage m = {}; EsMessage m = {};
m.type = ES_MSG_INSTANCE_SAVE; m.type = ES_MSG_INSTANCE_SAVE;
m.instanceSave.file = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore), true); m.instanceSave.file = (EsFileStore *) EsHeapAllocate(sizeof(EsFileStore), true);
m.instanceSave.file->error = message.message.tabOperation.error;
m.instanceSave.file->handle = message.message.tabOperation.handle;
m.instanceSave.file->type = FILE_STORE_HANDLE;
m.instanceSave.file->handles = 1;
m.instanceSave.instance = InstanceFromWindowID(message.message.tabOperation.id);
if (m.instanceSave.file->error == ES_SUCCESS) { if (m.instanceSave.file) {
m.instanceSave.file->error = message.message.tabOperation.error;
m.instanceSave.file->handle = message.message.tabOperation.handle;
m.instanceSave.file->type = FILE_STORE_HANDLE;
m.instanceSave.file->handles = 1;
m.instanceSave.instance = InstanceFromWindowID(message.message.tabOperation.id);
if (m.instanceSave.file->error == ES_SUCCESS) {
EsMemoryCopy(&message.message, &m, sizeof(EsMessage));
return &message.message;
} else {
EsInstanceSaveComplete(&m, false);
}
EsMemoryCopy(&message.message, &m, sizeof(EsMessage)); EsMemoryCopy(&message.message, &m, sizeof(EsMessage));
return &message.message;
} else { } else {
EsInstanceSaveComplete(&m, false); if (message.message.tabOperation.handle) {
EsHandleClose(message.message.tabOperation.handle);
}
} }
EsMemoryCopy(&message.message, &m, sizeof(EsMessage));
} else if (type == ES_MSG_INSTANCE_DOCUMENT_RENAMED) { } else if (type == ES_MSG_INSTANCE_DOCUMENT_RENAMED) {
char *buffer = (char *) EsHeapAllocate(message.message.tabOperation.bytes, false); char *buffer = (char *) EsHeapAllocate(message.message.tabOperation.bytes, false);
EsConstantBufferRead(message.message.tabOperation.handle, buffer);
EsInstance *_instance = InstanceFromWindowID(message.message.tabOperation.id);
if (_instance) { if (buffer) {
APIInstance *instance = (APIInstance *) _instance->_private; EsConstantBufferRead(message.message.tabOperation.handle, buffer);
EsHeapFree((void *) instance->startupInformation->filePath); EsInstance *_instance = InstanceFromWindowID(message.message.tabOperation.id);
instance->startupInformation->filePath = buffer;
instance->startupInformation->filePathBytes = message.message.tabOperation.bytes; if (_instance) {
EsWindowSetTitle(_instance->window, buffer, message.message.tabOperation.bytes); APIInstance *instance = (APIInstance *) _instance->_private;
} else { EsHeapFree((void *) instance->startupInformation->filePath);
EsHeapFree(buffer); instance->startupInformation->filePath = buffer;
instance->startupInformation->filePathBytes = message.message.tabOperation.bytes;
EsWindowSetTitle(_instance->window, buffer, message.message.tabOperation.bytes);
} else {
EsHeapFree(buffer);
}
} }
EsHandleClose(message.message.tabOperation.handle); EsHandleClose(message.message.tabOperation.handle);
@ -1014,7 +1049,9 @@ EsMessage *EsMessageReceive() {
api.foundBootFileSystem = true; api.foundBootFileSystem = true;
} }
return &message.message; if (m->mountPoint) {
return &message.message;
}
} else if (type == ES_MSG_UNREGISTER_FILE_SYSTEM) { } else if (type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) { for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
if (api.mountPoints[i].information.id == message.message.unregisterFileSystem.id) { if (api.mountPoints[i].information.id == message.message.unregisterFileSystem.id) {
@ -1279,6 +1316,7 @@ EsCommand *EsCommandRegister(EsCommand *command, EsInstance *_instance, EsComman
const char *cDefaultKeyboardShortcut, bool enabled) { const char *cDefaultKeyboardShortcut, bool enabled) {
if (!command) { if (!command) {
command = (EsCommand *) EsHeapAllocate(sizeof(EsCommand), true); command = (EsCommand *) EsHeapAllocate(sizeof(EsCommand), true);
if (!command) return nullptr;
command->allocated = true; command->allocated = true;
} }

View File

@ -394,17 +394,25 @@ struct ColorPickerHost {
void ColorPickerCreate(EsElement *parent, ColorPickerHost host, uint32_t initialColor, bool showTextbox); void ColorPickerCreate(EsElement *parent, ColorPickerHost host, uint32_t initialColor, bool showTextbox);
void HeapDuplicate(void **pointer, const void *data, size_t bytes) { void HeapDuplicate(void **pointer, size_t *outBytes, const void *data, size_t bytes) {
if (*pointer) { if (*pointer) {
EsHeapFree(*pointer); EsHeapFree(*pointer);
} }
if (!data && !bytes) { if (!data && !bytes) {
*pointer = nullptr; *pointer = nullptr;
*outBytes = 0;
} else { } else {
void *buffer = EsHeapAllocate(bytes, false); void *buffer = EsHeapAllocate(bytes, false);
if (buffer) EsMemoryCopy(buffer, data, bytes);
*pointer = buffer; if (buffer) {
EsMemoryCopy(buffer, data, bytes);
*pointer = buffer;
*outBytes = bytes;
} else {
*pointer = nullptr;
*outBytes = 0;
}
} }
} }
@ -674,7 +682,9 @@ void EsDialogClose(EsWindow *window) {
EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titleBytes, EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titleBytes,
const char *content, ptrdiff_t contentBytes, uint32_t iconID, uint32_t flags) { const char *content, ptrdiff_t contentBytes, uint32_t iconID, uint32_t flags) {
EsElement *dialog = EsDialogShow(window); EsElement *dialog = EsDialogShow(window);
if (!dialog) return nullptr;
EsPanel *heading = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_DIALOG_HEADING); EsPanel *heading = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_DIALOG_HEADING);
if (!heading) return nullptr;
if (iconID) { if (iconID) {
EsIconDisplayCreate(heading, ES_FLAGS_DEFAULT, {}, iconID); EsIconDisplayCreate(heading, ES_FLAGS_DEFAULT, {}, iconID);
@ -687,6 +697,7 @@ EsElement *EsDialogShowAlert(EsWindow *window, const char *title, ptrdiff_t titl
content, contentBytes)->cName = "dialog contents"; content, contentBytes)->cName = "dialog contents";
EsPanel *buttonArea = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE, ES_STYLE_DIALOG_BUTTON_AREA); EsPanel *buttonArea = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL | ES_PANEL_REVERSE, ES_STYLE_DIALOG_BUTTON_AREA);
if (!buttonArea) return nullptr;
if (flags & ES_DIALOG_ALERT_OK_BUTTON) { if (flags & ES_DIALOG_ALERT_OK_BUTTON) {
EsButton *button = EsButtonCreate(buttonArea, ES_BUTTON_DEFAULT, 0, "OK"); EsButton *button = EsButtonCreate(buttonArea, ES_BUTTON_DEFAULT, 0, "OK");
@ -821,7 +832,13 @@ EsWindow *EsWindowCreate(EsInstance *instance, EsWindowStyle style) {
} }
EsWindow *window = (EsWindow *) EsHeapAllocate(sizeof(EsWindow), true); EsWindow *window = (EsWindow *) EsHeapAllocate(sizeof(EsWindow), true);
gui.allWindows.Add(window); if (!window) return nullptr;
if (!gui.allWindows.Add(window)) {
EsHeapFree(window);
return nullptr;
}
window->instance = instance; window->instance = instance;
if (style == ES_WINDOW_NORMAL) { if (style == ES_WINDOW_NORMAL) {
@ -945,6 +962,7 @@ EsElement *EsMenuGetSource(EsMenu *menu) {
EsMenu *EsMenuCreate(EsElement *source, uint64_t flags) { EsMenu *EsMenuCreate(EsElement *source, uint64_t flags) {
EsWindow *menu = (EsWindow *) EsWindowCreate(source->instance, ES_WINDOW_MENU); EsWindow *menu = (EsWindow *) EsWindowCreate(source->instance, ES_WINDOW_MENU);
if (!menu) return nullptr;
menu->flags |= flags; menu->flags |= flags;
menu->activated = true; menu->activated = true;
menu->source = source; menu->source = source;
@ -1063,11 +1081,13 @@ void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
APIInstance *instance = (APIInstance *) _instance->_private; APIInstance *instance = (APIInstance *) _instance->_private;
EsAssert(instance->instanceClass == ES_INSTANCE_CLASS_EDITOR); EsAssert(instance->instanceClass == ES_INSTANCE_CLASS_EDITOR);
EsInstanceClassEditorSettings *editorSettings = &instance->editorSettings; EsInstanceClassEditorSettings *editorSettings = &instance->editorSettings;
EsMenu *menu = EsMenuCreate(element, ES_FLAGS_DEFAULT);
EsPanel *panel1 = EsPanelCreate(menu, ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel1);
bool newDocument = !instance->startupInformation || !instance->startupInformation->filePath; bool newDocument = !instance->startupInformation || !instance->startupInformation->filePath;
EsMenu *menu = EsMenuCreate(element, ES_FLAGS_DEFAULT);
if (!menu) return;
EsPanel *panel1 = EsPanelCreate(menu, ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel1);
if (!panel1) goto show;
{ {
// TODO Get this icon from the file type database? // TODO Get this icon from the file type database?
// We'll probably need Desktop to send this via EsApplicationStartupInformation and when the file is renamed. // We'll probably need Desktop to send this via EsApplicationStartupInformation and when the file is renamed.
@ -1076,7 +1096,9 @@ void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
EsSpacerCreate(panel1, ES_FLAGS_DEFAULT, 0, 5, 0); EsSpacerCreate(panel1, ES_FLAGS_DEFAULT, 0, 5, 0);
EsPanel *panel2 = EsPanelCreate(panel1, ES_FLAGS_DEFAULT, &styleFileMenuDocumentInformationPanel2); EsPanel *panel2 = EsPanelCreate(panel1, ES_FLAGS_DEFAULT, &styleFileMenuDocumentInformationPanel2);
if (!panel2) goto show;
EsPanel *panel3 = EsPanelCreate(panel2, ES_PANEL_HORIZONTAL | ES_PANEL_H_LEFT, &styleFileMenuDocumentInformationPanel2); EsPanel *panel3 = EsPanelCreate(panel2, ES_PANEL_HORIZONTAL | ES_PANEL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel3) goto show;
if (newDocument) { if (newDocument) {
EsTextDisplayCreate(panel3, ES_FLAGS_DEFAULT, ES_STYLE_TEXT_LABEL, EsTextDisplayCreate(panel3, ES_FLAGS_DEFAULT, ES_STYLE_TEXT_LABEL,
@ -1087,10 +1109,12 @@ void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
} }
EsButton *renameButton = EsButtonCreate(panel3, ES_BUTTON_TOOLBAR); // TODO. EsButton *renameButton = EsButtonCreate(panel3, ES_BUTTON_TOOLBAR); // TODO.
if (!renameButton) goto show;
EsButtonSetIcon(renameButton, ES_ICON_DOCUMENT_EDIT_SYMBOLIC); EsButtonSetIcon(renameButton, ES_ICON_DOCUMENT_EDIT_SYMBOLIC);
if (!newDocument) { if (!newDocument) {
EsPanel *panel4 = EsPanelCreate(panel2, ES_PANEL_TABLE | ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel2); EsPanel *panel4 = EsPanelCreate(panel2, ES_PANEL_TABLE | ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel4) goto show;
EsPanelSetBands(panel4, 2 /* columns */); EsPanelSetBands(panel4, 2 /* columns */);
char buffer[64]; char buffer[64];
@ -1120,11 +1144,13 @@ void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShare)); // TODO. EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShare)); // TODO.
EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileVersionHistory)); // TODO. EsMenuAddItem(menu, newDocument ? ES_ELEMENT_DISABLED : ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileVersionHistory)); // TODO.
EsMenuAddCommand(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShowInFileManager), &instance->commandShowInFileManager); EsMenuAddCommand(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShowInFileManager), &instance->commandShowInFileManager);
EsMenuShow(menu);
show: EsMenuShow(menu);
} }
void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings) { void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings) {
EsButton *button = EsButtonCreate(element, ES_BUTTON_DROPDOWN, 0, INTERFACE_STRING(CommonFileMenu)); EsButton *button = EsButtonCreate(element, ES_BUTTON_DROPDOWN, 0, INTERFACE_STRING(CommonFileMenu));
if (!button) return;
button->accessKey = 'F'; button->accessKey = 'F';
button->userData = (void *) settings; button->userData = (void *) settings;
EsButtonOnCommand(button, FileMenuCreate); EsButtonOnCommand(button, FileMenuCreate);
@ -1651,7 +1677,7 @@ void EsElement::InternalPaint(EsPainter *painter, int paintFlags) {
bool EsElement::StartAnimating() { bool EsElement::StartAnimating() {
if ((state & UI_STATE_ANIMATING) || (state & UI_STATE_DESTROYING)) return false; if ((state & UI_STATE_ANIMATING) || (state & UI_STATE_DESTROYING)) return false;
gui.animatingElements.Add(this); if (!gui.animatingElements.Add(this)) return false;
gui.animationSleep = false; gui.animationSleep = false;
state |= UI_STATE_ANIMATING; state |= UI_STATE_ANIMATING;
lastTimeStamp = 0; lastTimeStamp = 0;
@ -2703,6 +2729,7 @@ int ProcessScrollbarButtonMessage(EsElement *element, EsMessage *message) {
EsScrollbar *ScrollbarCreate(EsElement *parent, uint64_t flags) { EsScrollbar *ScrollbarCreate(EsElement *parent, uint64_t flags) {
EsScrollbar *scrollbar = (EsScrollbar *) EsHeapAllocate(sizeof(EsScrollbar), true); EsScrollbar *scrollbar = (EsScrollbar *) EsHeapAllocate(sizeof(EsScrollbar), true);
if (!scrollbar) return nullptr;
scrollbar->thumb = (EsElement *) EsHeapAllocate(sizeof(EsElement), true); scrollbar->thumb = (EsElement *) EsHeapAllocate(sizeof(EsElement), true);
if (flags & ES_SCROLLBAR_HORIZONTAL) { if (flags & ES_SCROLLBAR_HORIZONTAL) {
@ -2792,7 +2819,15 @@ void ScrollPane::Setup(EsElement *_parent, uint8_t _xMode, uint8_t _yMode, uint1
for (int axis = 0; axis < 2; axis++) { for (int axis = 0; axis < 2; axis++) {
if (mode[axis] == SCROLL_MODE_FIXED || mode[axis] == SCROLL_MODE_AUTO) { if (mode[axis] == SCROLL_MODE_FIXED || mode[axis] == SCROLL_MODE_AUTO) {
uint64_t flags = ES_CELL_FILL | ES_ELEMENT_NON_CLIENT | (axis ? ES_SCROLLBAR_VERTICAL : ES_SCROLLBAR_HORIZONTAL); uint64_t flags = ES_CELL_FILL | ES_ELEMENT_NON_CLIENT | (axis ? ES_SCROLLBAR_VERTICAL : ES_SCROLLBAR_HORIZONTAL);
if (!bar[axis]) bar[axis] = ScrollbarCreate(parent, flags);
if (!bar[axis]) {
bar[axis] = ScrollbarCreate(parent, flags);
if (!bar[axis]) {
continue;
}
}
bar[axis]->userData = this; bar[axis]->userData = this;
bar[axis]->messageUser = [] (EsElement *element, EsMessage *message) { bar[axis]->messageUser = [] (EsElement *element, EsMessage *message) {
@ -2816,7 +2851,7 @@ void ScrollPane::Setup(EsElement *_parent, uint8_t _xMode, uint8_t _yMode, uint1
if (bar[0] && bar[1]) { if (bar[0] && bar[1]) {
if (!pad) pad = EsCustomElementCreate(parent, ES_CELL_FILL | ES_ELEMENT_NON_CLIENT, ES_STYLE_SCROLLBAR_PAD); if (!pad) pad = EsCustomElementCreate(parent, ES_CELL_FILL | ES_ELEMENT_NON_CLIENT, ES_STYLE_SCROLLBAR_PAD);
pad->cName = "scrollbar pad"; if (pad) pad->cName = "scrollbar pad";
} else if (pad) { } else if (pad) {
EsElementDestroy(pad); EsElementDestroy(pad);
pad = nullptr; pad = nullptr;
@ -3333,6 +3368,7 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
EsPanel *EsPanelCreate(EsElement *parent, uint64_t flags, const EsStyle *style) { EsPanel *EsPanelCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsPanel *panel = (EsPanel *) EsHeapAllocate(sizeof(EsPanel), true); EsPanel *panel = (EsPanel *) EsHeapAllocate(sizeof(EsPanel), true);
if (!panel) return nullptr;
panel->Initialise(parent, flags, ProcessPanelMessage, style); panel->Initialise(parent, flags, ProcessPanelMessage, style);
panel->cName = "panel"; panel->cName = "panel";
@ -3367,6 +3403,7 @@ int ProcessSpacerMessage(EsElement *element, EsMessage *message) {
EsElement *EsSpacerCreate(EsElement *panel, uint64_t flags, const EsStyle *style, int width, int height) { EsElement *EsSpacerCreate(EsElement *panel, uint64_t flags, const EsStyle *style, int width, int height) {
EsSpacer *spacer = (EsSpacer *) EsHeapAllocate(sizeof(EsSpacer), true); EsSpacer *spacer = (EsSpacer *) EsHeapAllocate(sizeof(EsSpacer), true);
if (!spacer) return nullptr;
spacer->Initialise(panel, flags, ProcessSpacerMessage, style); spacer->Initialise(panel, flags, ProcessSpacerMessage, style);
spacer->cName = "spacer"; spacer->cName = "spacer";
spacer->width = width == -1 ? 4 : width; spacer->width = width == -1 ? 4 : width;
@ -3376,6 +3413,7 @@ EsElement *EsSpacerCreate(EsElement *panel, uint64_t flags, const EsStyle *style
EsElement *EsCustomElementCreate(EsElement *parent, uint64_t flags, const EsStyle *style) { EsElement *EsCustomElementCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsElement *element = (EsElement *) EsHeapAllocate(sizeof(EsElement), true); EsElement *element = (EsElement *) EsHeapAllocate(sizeof(EsElement), true);
if (!element) return nullptr;
element->Initialise(parent, flags, nullptr, style); element->Initialise(parent, flags, nullptr, style);
element->cName = "custom element"; element->cName = "custom element";
return element; return element;
@ -3604,6 +3642,7 @@ int ProcessCanvasPaneMessage(EsElement *element, EsMessage *message) {
EsCanvasPane *EsCanvasPaneCreate(EsElement *parent, uint64_t flags, const EsStyle *style) { EsCanvasPane *EsCanvasPaneCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsCanvasPane *pane = (EsCanvasPane *) EsHeapAllocate(sizeof(EsCanvasPane), true); EsCanvasPane *pane = (EsCanvasPane *) EsHeapAllocate(sizeof(EsCanvasPane), true);
if (!pane) return nullptr;
pane->Initialise(parent, flags, ProcessCanvasPaneMessage, style); pane->Initialise(parent, flags, ProcessCanvasPaneMessage, style);
pane->cName = "canvas pane"; pane->cName = "canvas pane";
pane->zoom = 1.0; pane->zoom = 1.0;
@ -3659,12 +3698,12 @@ void EsAnnouncementShow(EsWindow *parent, uint64_t flags, int32_t x, int32_t y,
(void) flags; (void) flags;
EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_TIP); EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_TIP);
if (!window) return;
window->messageUser = AnnouncementMessage; window->messageUser = AnnouncementMessage;
EsTextDisplay *display = EsTextDisplayCreate(window, ES_CELL_FILL, ES_STYLE_ANNOUNCEMENT, text, textBytes); EsTextDisplay *display = EsTextDisplayCreate(window, ES_CELL_FILL, ES_STYLE_ANNOUNCEMENT, text, textBytes);
int32_t width = display ? display->GetWidth(0) : 0;
int32_t width = display->GetWidth(0); int32_t height = display ? display->GetHeight(width) : 0;
int32_t height = display->GetHeight(width);
EsRectangle parentBounds = {}; EsRectangle parentBounds = {};
if (parent) parentBounds = EsWindowGetBounds(parent); if (parent) parentBounds = EsWindowGetBounds(parent);
@ -3778,6 +3817,7 @@ int ProcessButtonMessage(EsElement *element, EsMessage *message) {
EsButton *EsButtonCreate(EsElement *parent, uint64_t flags, const EsStyle *style, const char *label, ptrdiff_t labelBytes) { EsButton *EsButtonCreate(EsElement *parent, uint64_t flags, const EsStyle *style, const char *label, ptrdiff_t labelBytes) {
EsButton *button = (EsButton *) EsHeapAllocate(sizeof(EsButton), true); EsButton *button = (EsButton *) EsHeapAllocate(sizeof(EsButton), true);
if (!button) return button;
if (!style) { if (!style) {
if (flags & ES_BUTTON_MENU_ITEM) { if (flags & ES_BUTTON_MENU_ITEM) {
@ -3826,8 +3866,7 @@ EsButton *EsButtonCreate(EsElement *parent, uint64_t flags, const EsStyle *style
} }
if (labelBytes == -1) labelBytes = EsCStringLength(label); if (labelBytes == -1) labelBytes = EsCStringLength(label);
HeapDuplicate((void **) &button->label, label, labelBytes); HeapDuplicate((void **) &button->label, &button->labelBytes, label, labelBytes);
button->labelBytes = labelBytes;
if ((flags & ES_BUTTON_MENU_ITEM) && (flags & ES_MENU_ITEM_HEADER)) { if ((flags & ES_BUTTON_MENU_ITEM) && (flags & ES_MENU_ITEM_HEADER)) {
EsElementSetDisabled(button, true); EsElementSetDisabled(button, true);
@ -3904,6 +3943,7 @@ void EsMenuAddItem(EsMenu *menu, uint64_t flags, const char *label, ptrdiff_t la
EsButton *button = (EsButton *) EsButtonCreate(menu, EsButton *button = (EsButton *) EsButtonCreate(menu,
ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_MENU_ITEM | ES_CELL_H_FILL | flags, 0, ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_MENU_ITEM | ES_CELL_H_FILL | flags, 0,
label, labelBytes != -1 ? labelBytes : EsCStringLength(label)); label, labelBytes != -1 ? labelBytes : EsCStringLength(label));
if (!button) return;
button->userData = (void *) callback; button->userData = (void *) callback;
button->messageUser = [] (EsElement *element, EsMessage *message) { button->messageUser = [] (EsElement *element, EsMessage *message) {
@ -3926,6 +3966,7 @@ void EsMenuAddCommand(EsMenu *menu, uint64_t flags, const char *label, ptrdiff_t
EsButton *button = (EsButton *) EsButtonCreate(menu, EsButton *button = (EsButton *) EsButtonCreate(menu,
ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_MENU_ITEM | ES_CELL_H_FILL | flags, ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_MENU_ITEM | ES_CELL_H_FILL | flags,
0, label, labelBytes); 0, label, labelBytes);
if (!button) return;
EsCommandAddButton(command, button); EsCommandAddButton(command, button);
} }
@ -4131,6 +4172,7 @@ int ProcessColorChosenPointMessage(EsElement *element, EsMessage *message) {
void ColorPickerCreate(EsElement *parent, ColorPickerHost host, uint32_t initialColor, bool showTextbox) { void ColorPickerCreate(EsElement *parent, ColorPickerHost host, uint32_t initialColor, bool showTextbox) {
ColorPicker *picker = (ColorPicker *) EsHeapAllocate(sizeof(ColorPicker), true); ColorPicker *picker = (ColorPicker *) EsHeapAllocate(sizeof(ColorPicker), true);
if (!picker) return;
picker->host = host; picker->host = host;
picker->color = initialColor & 0xFFFFFF; picker->color = initialColor & 0xFFFFFF;
picker->opacity = (float) (initialColor >> 24) / 255.0f; picker->opacity = (float) (initialColor >> 24) / 255.0f;
@ -4500,6 +4542,7 @@ int ProcessColorWellMessage(EsElement *element, EsMessage *message) {
DrawStyledBox(message->painter, box); DrawStyledBox(message->painter, box);
} else if (message->type == ES_MSG_MOUSE_LEFT_CLICK) { } else if (message->type == ES_MSG_MOUSE_LEFT_CLICK) {
EsMenu *menu = EsMenuCreate(well, ES_FLAGS_DEFAULT); EsMenu *menu = EsMenuCreate(well, ES_FLAGS_DEFAULT);
if (!menu) return ES_HANDLED;
ColorPickerHost host = { well, &well->indeterminate, (well->flags & ES_COLOR_WELL_HAS_OPACITY) ? true : false }; ColorPickerHost host = { well, &well->indeterminate, (well->flags & ES_COLOR_WELL_HAS_OPACITY) ? true : false };
ColorPickerCreate((EsElement *) menu, host, well->color, true); ColorPickerCreate((EsElement *) menu, host, well->color, true);
EsMenuShow(menu); EsMenuShow(menu);
@ -4512,6 +4555,7 @@ int ProcessColorWellMessage(EsElement *element, EsMessage *message) {
EsColorWell *EsColorWellCreate(EsElement *parent, uint64_t flags, uint32_t initialColor) { EsColorWell *EsColorWellCreate(EsElement *parent, uint64_t flags, uint32_t initialColor) {
EsColorWell *well = (EsColorWell *) EsHeapAllocate(sizeof(EsColorWell), true); EsColorWell *well = (EsColorWell *) EsHeapAllocate(sizeof(EsColorWell), true);
if (!well) return nullptr;
well->color = initialColor; well->color = initialColor;
well->Initialise(parent, flags | ES_ELEMENT_FOCUSABLE, ProcessColorWellMessage, ES_STYLE_PUSH_BUTTON_NORMAL_COLOR_WELL); well->Initialise(parent, flags | ES_ELEMENT_FOCUSABLE, ProcessColorWellMessage, ES_STYLE_PUSH_BUTTON_NORMAL_COLOR_WELL);
well->cName = "color well"; well->cName = "color well";
@ -4706,6 +4750,11 @@ int ProcessSplitterMessage(EsElement *element, EsMessage *message) {
currentSizes.Add(splitter->resizeStartSizes[i]); currentSizes.Add(splitter->resizeStartSizes[i]);
} }
if (currentSizes.Length() != childCount / 2 + 1) {
currentSizes.Free();
return ES_HANDLED;
}
// Step 2: Calculate the fixed size, and total weight. // Step 2: Calculate the fixed size, and total weight.
int64_t fixedSize = 0, totalWeight = 0; int64_t fixedSize = 0, totalWeight = 0;
@ -4867,6 +4916,7 @@ int ProcessSplitterMessage(EsElement *element, EsMessage *message) {
EsSplitter *EsSplitterCreate(EsElement *parent, uint64_t flags, const EsStyle *style) { EsSplitter *EsSplitterCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsSplitter *splitter = (EsSplitter *) EsHeapAllocate(sizeof(EsSplitter), true); EsSplitter *splitter = (EsSplitter *) EsHeapAllocate(sizeof(EsSplitter), true);
if (!splitter) return nullptr;
splitter->horizontal = flags & ES_SPLITTER_HORIZONTAL; splitter->horizontal = flags & ES_SPLITTER_HORIZONTAL;
splitter->Initialise(parent, flags | ES_ELEMENT_NO_CLIP, ProcessSplitterMessage, splitter->Initialise(parent, flags | ES_ELEMENT_NO_CLIP, ProcessSplitterMessage,
style ?: ES_STYLE_PANEL_WINDOW_BACKGROUND); style ?: ES_STYLE_PANEL_WINDOW_BACKGROUND);
@ -4914,8 +4964,9 @@ int ProcessImageDisplayMessage(EsElement *element, EsMessage *message) {
} }
if (~display->flags & UI_STATE_CHECK_VISIBLE) { if (~display->flags & UI_STATE_CHECK_VISIBLE) {
display->state |= UI_STATE_CHECK_VISIBLE; if (display->window->checkVisible.Add(display)) {
display->window->checkVisible.Add(display); display->state |= UI_STATE_CHECK_VISIBLE;
}
} }
} }
@ -4944,6 +4995,7 @@ int ProcessImageDisplayMessage(EsElement *element, EsMessage *message) {
EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style) { EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsImageDisplay *display = (EsImageDisplay *) EsHeapAllocate(sizeof(EsImageDisplay), true); EsImageDisplay *display = (EsImageDisplay *) EsHeapAllocate(sizeof(EsImageDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessImageDisplayMessage, style); display->Initialise(parent, flags, ProcessImageDisplayMessage, style);
display->cName = "image"; display->cName = "image";
return display; return display;
@ -5009,6 +5061,7 @@ int ProcessIconDisplayMessage(EsElement *element, EsMessage *message) {
EsIconDisplay *EsIconDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style, uint32_t iconID) { EsIconDisplay *EsIconDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style, uint32_t iconID) {
EsIconDisplay *display = (EsIconDisplay *) EsHeapAllocate(sizeof(EsIconDisplay), true); EsIconDisplay *display = (EsIconDisplay *) EsHeapAllocate(sizeof(EsIconDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessIconDisplayMessage, style ?: ES_STYLE_ICON_DISPLAY); display->Initialise(parent, flags, ProcessIconDisplayMessage, style ?: ES_STYLE_ICON_DISPLAY);
display->cName = "icon"; display->cName = "icon";
display->iconID = iconID; display->iconID = iconID;
@ -5101,6 +5154,7 @@ void EsSliderSetValue(EsSlider *slider, double newValue, bool sendUpdatedMessage
EsSlider *EsSliderCreate(EsElement *parent, uint64_t flags, const EsStyle *style, double value, uint32_t steps) { EsSlider *EsSliderCreate(EsElement *parent, uint64_t flags, const EsStyle *style, double value, uint32_t steps) {
EsSlider *slider = (EsSlider *) EsHeapAllocate(sizeof(EsSlider), true); EsSlider *slider = (EsSlider *) EsHeapAllocate(sizeof(EsSlider), true);
if (!slider) return nullptr;
slider->Initialise(parent, flags | ES_ELEMENT_FOCUSABLE, ProcessSliderMessage, style ?: ES_STYLE_SLIDER_TRACK); slider->Initialise(parent, flags | ES_ELEMENT_FOCUSABLE, ProcessSliderMessage, style ?: ES_STYLE_SLIDER_TRACK);
slider->cName = "slider"; slider->cName = "slider";
slider->point = EsCustomElementCreate(slider, ES_FLAGS_DEFAULT, ES_STYLE_SLIDER_POINT); slider->point = EsCustomElementCreate(slider, ES_FLAGS_DEFAULT, ES_STYLE_SLIDER_POINT);
@ -5254,6 +5308,11 @@ EsElement *EsWindowGetToolbar(EsWindow *window, bool createNew) {
if (createNew || !window->toolbar) { if (createNew || !window->toolbar) {
bool first = !window->toolbar; bool first = !window->toolbar;
window->toolbar = EsPanelCreate(window->toolbarSwitcher, ES_PANEL_HORIZONTAL | ES_CELL_FILL, ES_STYLE_PANEL_TOOLBAR); window->toolbar = EsPanelCreate(window->toolbarSwitcher, ES_PANEL_HORIZONTAL | ES_CELL_FILL, ES_STYLE_PANEL_TOOLBAR);
if (!window->toolbar) {
return nullptr;
}
window->toolbar->cName = "toolbar"; window->toolbar->cName = "toolbar";
EsAssert(window->toolbar->messageClass == ProcessPanelMessage); EsAssert(window->toolbar->messageClass == ProcessPanelMessage);
@ -6099,8 +6158,9 @@ void AccessKeysGather(EsElement *element) {
entry.bounds = hintBounds; entry.bounds = hintBounds;
gui.accessKeys.entries.Add(entry); if (gui.accessKeys.entries.Add(entry)) {
gui.accessKeys.numbers[entry.character - 'A']++; gui.accessKeys.numbers[entry.character - 'A']++;
}
} }
void AccessKeyHintsShow(EsPainter *painter) { void AccessKeyHintsShow(EsPainter *painter) {
@ -7071,8 +7131,7 @@ int InspectorContentTextboxCallback(EsElement *element, EsMessage *message) {
if (e->messageClass == ProcessButtonMessage) { if (e->messageClass == ProcessButtonMessage) {
EsButton *button = (EsButton *) e; EsButton *button = (EsButton *) e;
HeapDuplicate((void **) &button->label, newContent, newContentBytes); HeapDuplicate((void **) &button->label, &button->labelBytes, newContent, newContentBytes);
button->labelBytes = newContentBytes;
} else if (e->messageClass == ProcessTextDisplayMessage) { } else if (e->messageClass == ProcessTextDisplayMessage) {
EsTextDisplay *display = (EsTextDisplay *) e; EsTextDisplay *display = (EsTextDisplay *) e;
EsTextDisplaySetContents(display, newContent, newContentBytes); EsTextDisplaySetContents(display, newContent, newContentBytes);

View File

@ -1979,6 +1979,7 @@ void EsListViewChangeStyles(EsListView *view, const EsStyle *style, const EsStyl
EsListView *EsListViewCreate(EsElement *parent, uint64_t flags, const EsStyle *style, EsListView *EsListViewCreate(EsElement *parent, uint64_t flags, const EsStyle *style,
const EsStyle *itemStyle, const EsStyle *headerItemStyle, const EsStyle *footerItemStyle) { const EsStyle *itemStyle, const EsStyle *headerItemStyle, const EsStyle *footerItemStyle) {
EsListView *view = (EsListView *) EsHeapAllocate(sizeof(EsListView), true); EsListView *view = (EsListView *) EsHeapAllocate(sizeof(EsListView), true);
if (!view) return nullptr;
view->primaryCellStyle = GetStyle(MakeStyleKey(ES_STYLE_LIST_PRIMARY_CELL, 0), false); view->primaryCellStyle = GetStyle(MakeStyleKey(ES_STYLE_LIST_PRIMARY_CELL, 0), false);
view->secondaryCellStyle = GetStyle(MakeStyleKey(ES_STYLE_LIST_SECONDARY_CELL, 0), false); view->secondaryCellStyle = GetStyle(MakeStyleKey(ES_STYLE_LIST_SECONDARY_CELL, 0), false);
@ -2009,7 +2010,10 @@ void EsListViewInsertGroup(EsListView *view, EsListViewIndex group, uint32_t fla
ListViewGroup empty = { .flags = flags }; ListViewGroup empty = { .flags = flags };
EsAssert(group <= (EsListViewIndex) view->groups.Length()); // Invalid group index. EsAssert(group <= (EsListViewIndex) view->groups.Length()); // Invalid group index.
view->groups.Insert(empty, group);
if (!view->groups.Insert(empty, group)) {
return;
}
// Update the group index on visible items. // Update the group index on visible items.
@ -2339,8 +2343,7 @@ void EsListViewSelect(EsListView *view, EsListViewIndex group, EsListViewIndex i
void EsListViewSetEmptyMessage(EsListView *view, const char *message, ptrdiff_t messageBytes) { void EsListViewSetEmptyMessage(EsListView *view, const char *message, ptrdiff_t messageBytes) {
EsMessageMutexCheck(); EsMessageMutexCheck();
if (messageBytes == -1) messageBytes = EsCStringLength(message); if (messageBytes == -1) messageBytes = EsCStringLength(message);
HeapDuplicate((void **) &view->emptyMessage, message, messageBytes); HeapDuplicate((void **) &view->emptyMessage, &view->emptyMessageBytes, message, messageBytes);
view->emptyMessageBytes = messageBytes;
if (!view->totalItemCount) { if (!view->totalItemCount) {
view->Repaint(true); view->Repaint(true);
@ -2389,8 +2392,7 @@ EsListViewIndex EsListViewFixedItemInsert(EsListView *view, const char *string,
ListViewFixedItem item = {}; ListViewFixedItem item = {};
item.data = data; item.data = data;
item.iconID = iconID; item.iconID = iconID;
HeapDuplicate((void **) &item.firstColumn.string, string, stringBytes); HeapDuplicate((void **) &item.firstColumn.string, &item.firstColumn.bytes, string, stringBytes);
item.firstColumn.bytes = stringBytes;
view->fixedItems.Insert(item, index); view->fixedItems.Insert(item, index);
EsListViewInsert(view, 0, index, 1); EsListViewInsert(view, 0, index, 1);
@ -2403,9 +2405,13 @@ void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, const
EsAssert(index >= 0 && index < (intptr_t) view->fixedItems.Length()); EsAssert(index >= 0 && index < (intptr_t) view->fixedItems.Length());
ListViewFixedString fixedString = {}; ListViewFixedString fixedString = {};
fixedString.bytes = stringBytes == -1 ? EsCStringLength(string) : stringBytes; fixedString.bytes = stringBytes == -1 ? EsCStringLength(string) : stringBytes;
HeapDuplicate((void **) &fixedString, string, fixedString.bytes); size_t outBytes;
view->fixedItems[index].otherColumns.Add(fixedString); HeapDuplicate((void **) &fixedString, &outBytes, string, fixedString.bytes);
EsListViewInvalidateContent(view, 0, index);
if (outBytes == fixedString.bytes) {
view->fixedItems[index].otherColumns.Add(fixedString);
EsListViewInvalidateContent(view, 0, index);
}
} }
bool EsListViewFixedItemFindIndex(EsListView *view, EsGeneric data, EsListViewIndex *index) { bool EsListViewFixedItemFindIndex(EsListView *view, EsGeneric data, EsListViewIndex *index) {
@ -2473,6 +2479,11 @@ EsTextbox *EsListViewCreateInlineTextbox(EsListView *view, EsListViewIndex group
} }
view->inlineTextbox = EsTextboxCreate(view, textboxFlags, ES_STYLE_TEXTBOX_INLINE); view->inlineTextbox = EsTextboxCreate(view, textboxFlags, ES_STYLE_TEXTBOX_INLINE);
if (!view->inlineTextbox) {
return nullptr;
}
EsAssert(view->inlineTextbox->messageClass == ProcessTextboxMessage); EsAssert(view->inlineTextbox->messageClass == ProcessTextboxMessage);
view->inlineTextbox->messageClass = ListViewInlineTextboxMessage; view->inlineTextbox->messageClass = ListViewInlineTextboxMessage;

View File

@ -187,12 +187,21 @@ void SettingsNumberBoxSetValue(EsElement *element, double newValueDouble) {
EsTextboxInsert(textbox, buffer, bytes); EsTextboxInsert(textbox, buffer, bytes);
EsMutexAcquire(&api.systemConfigurationMutex); EsMutexAcquire(&api.systemConfigurationMutex);
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true); EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true);
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true); int32_t oldValue = 0;
int32_t oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value); if (group) {
item->value = (char *) EsHeapAllocate(65, true); EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
item->valueBytes = EsStringFormat(item->value, 64, "%fd", ES_STRING_FORMAT_SIMPLE, newValue);
if (item) {
oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value);
item->value = (char *) EsHeapAllocate(65, true);
item->valueBytes = EsStringFormat(item->value, 64, "%fd", ES_STRING_FORMAT_SIMPLE, newValue);
}
}
EsMutexRelease(&api.systemConfigurationMutex); EsMutexRelease(&api.systemConfigurationMutex);
if (oldValue != newValue) { if (oldValue != newValue) {
@ -245,13 +254,22 @@ void SettingsCheckboxCommand(EsInstance *_instance, EsElement *element, EsComman
bool newValue = EsButtonGetCheck(button) == ES_CHECK_CHECKED; bool newValue = EsButtonGetCheck(button) == ES_CHECK_CHECKED;
EsMutexAcquire(&api.systemConfigurationMutex); EsMutexAcquire(&api.systemConfigurationMutex);
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true); EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true);
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true); bool oldValue;
bool oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value); if (group) {
item->value = (char *) EsHeapAllocate(2, true); EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
*item->value = newValue ? '1' : '0';
item->valueBytes = 1; if (item) {
oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value);
item->value = (char *) EsHeapAllocate(2, true);
*item->value = newValue ? '1' : '0';
item->valueBytes = 1;
}
}
EsMutexRelease(&api.systemConfigurationMutex); EsMutexRelease(&api.systemConfigurationMutex);
if (oldValue == newValue) return; if (oldValue == newValue) return;
@ -362,13 +380,22 @@ int SettingsSliderMessage(EsElement *element, EsMessage *message) {
if (message->type == ES_MSG_SLIDER_MOVED && !message->sliderMoved.inDrag) { if (message->type == ES_MSG_SLIDER_MOVED && !message->sliderMoved.inDrag) {
EsMutexAcquire(&api.systemConfigurationMutex); EsMutexAcquire(&api.systemConfigurationMutex);
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true); EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true);
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true); int32_t oldValue;
int32_t newValue = LinearMap(0, 1, control->minimumValue, control->maximumValue, EsSliderGetValue(slider)); int32_t newValue = LinearMap(0, 1, control->minimumValue, control->maximumValue, EsSliderGetValue(slider));
int32_t oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value); if (group) {
item->value = (char *) EsHeapAllocate(65, true); EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
item->valueBytes = EsStringFormat(item->value, 64, "%fd", ES_STRING_FORMAT_SIMPLE, newValue);
if (item) {
oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value);
item->value = (char *) EsHeapAllocate(65, true);
item->valueBytes = EsStringFormat(item->value, 64, "%fd", ES_STRING_FORMAT_SIMPLE, newValue);
}
}
EsMutexRelease(&api.systemConfigurationMutex); EsMutexRelease(&api.systemConfigurationMutex);
if (oldValue != newValue) { if (oldValue != newValue) {

View File

@ -800,6 +800,7 @@ EsFileStore *EsClipboardOpen(EsClipboard clipboard) {
EsBufferReadInto(&buffer, &error, sizeof(error)); EsBufferReadInto(&buffer, &error, sizeof(error));
EsHeapFree(buffer.out); EsHeapFree(buffer.out);
EsFileStore *fileStore = FileStoreCreateFromHandle(file); EsFileStore *fileStore = FileStoreCreateFromHandle(file);
if (!fileStore) return nullptr;
fileStore->error = error; fileStore->error = error;
return fileStore; return fileStore;
} }
@ -823,8 +824,13 @@ EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format,
EsError EsClipboardAddText(EsClipboard clipboard, const char *text, ptrdiff_t textBytes) { EsError EsClipboardAddText(EsClipboard clipboard, const char *text, ptrdiff_t textBytes) {
EsFileStore *fileStore = EsClipboardOpen(clipboard); EsFileStore *fileStore = EsClipboardOpen(clipboard);
EsFileStoreWriteAll(fileStore, text, textBytes);
return EsClipboardCloseAndAdd(clipboard, ES_CLIPBOARD_FORMAT_TEXT, fileStore); if (fileStore) {
EsFileStoreWriteAll(fileStore, text, textBytes);
return EsClipboardCloseAndAdd(clipboard, ES_CLIPBOARD_FORMAT_TEXT, fileStore);
} else {
return ES_ERROR_INSUFFICIENT_RESOURCES;
}
} }
void ClipboardGetInformation(EsHandle *file, ClipboardInformation *information) { void ClipboardGetInformation(EsHandle *file, ClipboardInformation *information) {

View File

@ -557,10 +557,7 @@ bool EsFontDatabaseLookupByID(EsFontFamily id, EsFontInformation *information) {
EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFileStore *store) { EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFileStore *store) {
FontInitialise(); FontInitialise();
EsAssert(store->handles); EsAssert(store->handles);
store->handles++;
FontDatabaseEntry *entry = nullptr; FontDatabaseEntry *entry = nullptr;
if (information->nameBytes) { if (information->nameBytes) {
@ -586,12 +583,18 @@ EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFi
FontDatabaseEntry e = {}; FontDatabaseEntry e = {};
EsMemoryCopy(&e, information, sizeof(EsFontInformation)); EsMemoryCopy(&e, information, sizeof(EsFontInformation));
e.id = fontManagement.database.Length(); e.id = fontManagement.database.Length();
fontManagement.database.Add(e);
entry = &fontManagement.database.Last(); if (fontManagement.database.Add(e)) {
entry = &fontManagement.database.Last();
} else {
return 0;
}
} }
addFileToFamily:; addFileToFamily:;
store->handles++;
entry->availableWeightsNormal |= information->availableWeightsNormal; entry->availableWeightsNormal |= information->availableWeightsNormal;
entry->availableWeightsItalic |= information->availableWeightsItalic; entry->availableWeightsItalic |= information->availableWeightsItalic;
@ -1846,13 +1849,13 @@ void TextAddEllipsis(EsTextPlan *plan, int32_t maximumLineWidth, bool needFinalE
TextPiece piece = {}; TextPiece piece = {};
piece.style = plan->currentTextStyle; piece.style = plan->currentTextStyle;
piece.glyphOffset = plan->glyphInfos.Length(); piece.glyphOffset = plan->glyphInfos.Length();
piece.glyphCount = glyphCount;
piece.ascent = FontGetAscent (&plan->font) + plan->currentTextStyle->baselineOffset, piece.ascent = FontGetAscent (&plan->font) + plan->currentTextStyle->baselineOffset,
piece.descent = -FontGetDescent(&plan->font) - plan->currentTextStyle->baselineOffset; piece.descent = -FontGetDescent(&plan->font) - plan->currentTextStyle->baselineOffset;
for (uintptr_t i = 0; i < glyphCount; i++) { for (uintptr_t i = 0; i < glyphCount; i++) {
plan->glyphInfos.Add(glyphInfos[i]); if (!plan->glyphInfos.Add(glyphInfos[i])) break;
plan->glyphPositions.Add(glyphPositions[i]); if (!plan->glyphPositions.Add(glyphPositions[i])) break;
piece.glyphCount++;
int32_t width = glyphPositions[i].x_advance; int32_t width = glyphPositions[i].x_advance;
piece.width += width, line->width += width; piece.width += width, line->width += width;
} }
@ -1938,18 +1941,19 @@ int32_t TextExpandTabs(EsTextPlan *plan, uintptr_t pieceOffset, int32_t width) {
piece->width = firstWidth + tabWidth * (piece->end - piece->start - 1); piece->width = firstWidth + tabWidth * (piece->end - piece->start - 1);
addedWidth += piece->width; addedWidth += piece->width;
piece->glyphOffset = plan->glyphInfos.Length(); piece->glyphOffset = plan->glyphInfos.Length();
piece->glyphCount = piece->end - piece->start; piece->glyphCount = 0;
piece->ascent = FontGetAscent(&plan->font); piece->ascent = FontGetAscent(&plan->font);
piece->descent = -FontGetDescent(&plan->font); piece->descent = -FontGetDescent(&plan->font);
for (uintptr_t i = 0; i < piece->glyphCount; i++) { for (uintptr_t i = 0; i < piece->end - piece->start; i++) {
hb_glyph_info_t info = {}; hb_glyph_info_t info = {};
info.cluster = piece->start + i; info.cluster = piece->start + i;
info.codepoint = 0xFFFFFFFF; info.codepoint = 0xFFFFFFFF;
hb_glyph_position_t position = {}; hb_glyph_position_t position = {};
position.x_advance = i ? tabWidth : firstWidth; position.x_advance = i ? tabWidth : firstWidth;
plan->glyphInfos.Add(info); if (!plan->glyphInfos.Add(info)) break;
plan->glyphPositions.Add(position); if (!plan->glyphPositions.Add(position)) break;
piece->glyphCount++;
} }
} }
@ -2004,14 +2008,17 @@ int32_t TextBuildTextPieces(EsTextPlan *plan, uintptr_t sectionStart, uintptr_t
if (plan->string[start] == '\t') { if (plan->string[start] == '\t') {
TextPiece _piece = {}; TextPiece _piece = {};
plan->pieces.Add(_piece);
TextPiece *piece = &plan->pieces.Last(); if (plan->pieces.Add(_piece)) {
piece->style = plan->currentTextStyle; TextPiece *piece = &plan->pieces.Last();
piece->glyphOffset = 0; piece->style = plan->currentTextStyle;
piece->glyphCount = 0; piece->glyphOffset = 0;
piece->start = start; piece->glyphCount = 0;
piece->end = end; piece->start = start;
piece->isTabPiece = true; piece->end = end;
piece->isTabPiece = true;
}
plan->textRunPosition++; plan->textRunPosition++;
continue; continue;
} }
@ -2041,31 +2048,34 @@ int32_t TextBuildTextPieces(EsTextPlan *plan, uintptr_t sectionStart, uintptr_t
// Create the text piece. // Create the text piece.
TextPiece _piece = {}; TextPiece _piece = {};
plan->pieces.Add(_piece);
TextPiece *piece = &plan->pieces.Last();
piece->style = plan->currentTextStyle;
piece->glyphOffset = plan->glyphInfos.Length();
piece->glyphCount = glyphCount;
piece->ascent = FontGetAscent (&plan->font) + plan->currentTextStyle->baselineOffset;
piece->descent = -FontGetDescent(&plan->font) - plan->currentTextStyle->baselineOffset;
piece->start = start;
piece->end = end;
for (uintptr_t i = 0; i < glyphCount; i++) { if (plan->pieces.Add(_piece)) {
plan->glyphInfos.Add(glyphInfos[i]); TextPiece *piece = &plan->pieces.Last();
plan->glyphPositions.Add(glyphPositions[i]); piece->style = plan->currentTextStyle;
piece->glyphOffset = plan->glyphInfos.Length();
piece->glyphCount = 0;
piece->ascent = FontGetAscent (&plan->font) + plan->currentTextStyle->baselineOffset;
piece->descent = -FontGetDescent(&plan->font) - plan->currentTextStyle->baselineOffset;
piece->start = start;
piece->end = end;
piece->width += glyphPositions[i].x_advance; for (uintptr_t i = 0; i < glyphCount; i++) {
if (!plan->glyphInfos.Add(glyphInfos[i])) break;
if (!plan->glyphPositions.Add(glyphPositions[i])) break;
piece->glyphCount++;
if (i == glyphCount - 1 || glyphInfos[i].cluster != glyphInfos[i + 1].cluster) { piece->width += glyphPositions[i].x_advance;
piece->width += plan->currentTextStyle->tracking * FREETYPE_UNIT_SCALE;
if (i == glyphCount - 1 || glyphInfos[i].cluster != glyphInfos[i + 1].cluster) {
piece->width += plan->currentTextStyle->tracking * FREETYPE_UNIT_SCALE;
}
// EsPrint("\t%d\n", glyphInfos[i].codepoint);
} }
// EsPrint("\t%d\n", glyphInfos[i].codepoint); width += piece->width;
} }
width += piece->width;
// Go to the next run. // Go to the next run.
plan->textRunPosition++; plan->textRunPosition++;
@ -2115,7 +2125,10 @@ EsTextPlan *EsTextPlanCreate(EsElement *element, EsTextPlanProperties *propertie
plan.properties = *properties; plan.properties = *properties;
TextLine blankLine = {}; TextLine blankLine = {};
plan.lines.Add(blankLine);
if (!plan.lines.Add(blankLine)) {
return nullptr;
}
// Setup the HarfBuzz buffer. // Setup the HarfBuzz buffer.
@ -2166,8 +2179,9 @@ EsTextPlan *EsTextPlanCreate(EsElement *element, EsTextPlanProperties *propertie
break; break;
} }
plan.lines.Add(blankLine); if (plan.lines.Add(blankLine)) {
plan.lines.Last().pieceOffset = pieceOffset; plan.lines.Last().pieceOffset = pieceOffset;
}
} }
#if 0 #if 0
@ -3980,7 +3994,14 @@ char *EsTextboxGetContents(EsTextbox *textbox, size_t *_bytes, uint32_t flags) {
buffer[position] = 0; buffer[position] = 0;
EsAssert(position <= bytes); EsAssert(position <= bytes);
if (_bytes) *_bytes = position; if (_bytes) *_bytes = position;
return (char *) EsHeapReallocate(buffer, position + 1, false);
char *result = (char *) EsHeapReallocate(buffer, position + 1, false);
if (!result) {
EsHeapFree(buffer);
}
return result;
} }
double EsTextboxGetContentsAsDouble(EsTextbox *textbox, uint32_t flags) { double EsTextboxGetContentsAsDouble(EsTextbox *textbox, uint32_t flags) {
@ -4210,7 +4231,8 @@ int ProcessTextboxMarginMessage(EsElement *element, EsMessage *message) {
textRun[1].offset = EsStringFormat(label, sizeof(label), "%d", i + textbox->firstVisibleLine + 1); textRun[1].offset = EsStringFormat(label, sizeof(label), "%d", i + textbox->firstVisibleLine + 1);
EsTextPlanProperties properties = {}; EsTextPlanProperties properties = {};
properties.flags = ES_TEXT_V_CENTER | ES_TEXT_H_RIGHT | ES_TEXT_ELLIPSIS | ES_TEXT_PLAN_SINGLE_USE; properties.flags = ES_TEXT_V_CENTER | ES_TEXT_H_RIGHT | ES_TEXT_ELLIPSIS | ES_TEXT_PLAN_SINGLE_USE;
EsDrawText(painter, EsTextPlanCreate(element, &properties, bounds, label, textRun, 1), bounds, nullptr, nullptr); EsTextPlan *plan = EsTextPlanCreate(element, &properties, bounds, label, textRun, 1);
if (plan) EsDrawText(painter, plan, bounds, nullptr, nullptr);
} }
} }
@ -4317,7 +4339,9 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
selectionProperties.caret1 = caret1; selectionProperties.caret1 = caret1;
EsTextPlan *plan; EsTextPlan *plan;
if (textRuns[1].offset) { if (!textRuns.Length()) {
plan = nullptr;
} else if (textRuns[1].offset) {
plan = EsTextPlanCreate(element, &properties, lineBounds, line->GetBuffer(textbox), textRuns.array, textRuns.Length() - 1); plan = EsTextPlanCreate(element, &properties, lineBounds, line->GetBuffer(textbox), textRuns.array, textRuns.Length() - 1);
} else { } else {
textRuns[1].offset = 1; // Make sure that the caret and selection is draw correctly, even on empty lines. textRuns[1].offset = 1; // Make sure that the caret and selection is draw correctly, even on empty lines.
@ -4503,6 +4527,7 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
} else if (message->type == ES_MSG_MOUSE_RIGHT_UP) { } else if (message->type == ES_MSG_MOUSE_RIGHT_UP) {
textbox->inRightClickDrag = false; textbox->inRightClickDrag = false;
EsMenu *menu = EsMenuCreate(textbox, ES_MENU_AT_CURSOR); EsMenu *menu = EsMenuCreate(textbox, ES_MENU_AT_CURSOR);
if (!menu) return ES_HANDLED;
// TODO User customisation of menus. // TODO User customisation of menus.
@ -4613,6 +4638,7 @@ int ProcessTextboxMessage(EsElement *element, EsMessage *message) {
EsTextbox *EsTextboxCreate(EsElement *parent, uint64_t flags, const EsStyle *style) { EsTextbox *EsTextboxCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsTextbox *textbox = (EsTextbox *) EsHeapAllocate(sizeof(EsTextbox), true); EsTextbox *textbox = (EsTextbox *) EsHeapAllocate(sizeof(EsTextbox), true);
if (!textbox) return nullptr;
if (!style) { if (!style) {
if (flags & ES_TEXTBOX_MULTILINE) { if (flags & ES_TEXTBOX_MULTILINE) {
@ -4767,6 +4793,10 @@ void TextboxBreadcrumbOverlayRecreate(EsTextbox *textbox) {
EsPanel *panel = EsPanelCreate(textbox, ES_PANEL_HORIZONTAL | ES_CELL_FILL | ES_ELEMENT_NO_HOVER, ES_STYLE_BREADCRUMB_BAR_PANEL); EsPanel *panel = EsPanelCreate(textbox, ES_PANEL_HORIZONTAL | ES_CELL_FILL | ES_ELEMENT_NO_HOVER, ES_STYLE_BREADCRUMB_BAR_PANEL);
textbox->overlayData = panel; textbox->overlayData = panel;
if (!panel) {
return;
}
uint8_t _buffer[256]; uint8_t _buffer[256];
EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) }; EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) };
EsMessage m = { ES_MSG_TEXTBOX_GET_BREADCRUMB }; EsMessage m = { ES_MSG_TEXTBOX_GET_BREADCRUMB };
@ -4780,19 +4810,22 @@ void TextboxBreadcrumbOverlayRecreate(EsTextbox *textbox) {
EsButton *crumb = EsButtonCreate(panel, ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_COMPACT | ES_CELL_V_FILL, EsButton *crumb = EsButtonCreate(panel, ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_COMPACT | ES_CELL_V_FILL,
ES_STYLE_BREADCRUMB_BAR_CRUMB, (char *) buffer.out, buffer.position); ES_STYLE_BREADCRUMB_BAR_CRUMB, (char *) buffer.out, buffer.position);
crumb->userData = m.getBreadcrumb.index;
crumb->messageUser = [] (EsElement *element, EsMessage *message) { if (crumb) {
if (message->type == ES_MSG_MOUSE_LEFT_CLICK) { crumb->userData = m.getBreadcrumb.index;
EsMessage m = { ES_MSG_TEXTBOX_ACTIVATE_BREADCRUMB };
m.activateBreadcrumb = element->userData.u;
EsMessageSend(element->parent->parent, &m);
} else {
return 0;
}
return ES_HANDLED; crumb->messageUser = [] (EsElement *element, EsMessage *message) {
}; if (message->type == ES_MSG_MOUSE_LEFT_CLICK) {
EsMessage m = { ES_MSG_TEXTBOX_ACTIVATE_BREADCRUMB };
m.activateBreadcrumb = element->userData.u;
EsMessageSend(element->parent->parent, &m);
} else {
return 0;
}
return ES_HANDLED;
};
}
m.getBreadcrumb.index++; m.getBreadcrumb.index++;
} }
@ -4954,7 +4987,14 @@ void EsTextDisplaySetStyledContents(EsTextDisplay *display, const char *string,
display->textRuns = (EsTextRun *) EsHeapAllocate(sizeof(EsTextRun) * (runCount + 1), true); display->textRuns = (EsTextRun *) EsHeapAllocate(sizeof(EsTextRun) * (runCount + 1), true);
display->textRunCount = runCount; display->textRunCount = runCount;
HeapDuplicate((void **) &display->contents, string, runs[runCount].offset);
size_t outBytes;
HeapDuplicate((void **) &display->contents, &outBytes, string, runs[runCount].offset);
if (outBytes != runs[runCount].offset) {
// TODO Handle allocation failure.
}
EsMemoryCopy(display->textRuns, runs, sizeof(EsTextRun) * (runCount + 1)); EsMemoryCopy(display->textRuns, runs, sizeof(EsTextRun) * (runCount + 1));
display->usingSyntaxHighlighting = false; display->usingSyntaxHighlighting = false;
@ -4973,7 +5013,7 @@ void EsTextDisplaySetContents(EsTextDisplay *display, const char *string, ptrdif
display->currentStyle->GetTextStyle(&baseStyle); display->currentStyle->GetTextStyle(&baseStyle);
EsRichTextParse(string, stringBytes, &display->contents, &display->textRuns, &display->textRunCount, &baseStyle); EsRichTextParse(string, stringBytes, &display->contents, &display->textRuns, &display->textRunCount, &baseStyle);
} else { } else {
HeapDuplicate((void **) &display->contents, string, stringBytes); HeapDuplicate((void **) &display->contents, (size_t *) &stringBytes, string, stringBytes);
display->textRuns = (EsTextRun *) EsHeapAllocate(sizeof(EsTextRun) * 2, true); display->textRuns = (EsTextRun *) EsHeapAllocate(sizeof(EsTextRun) * 2, true);
display->currentStyle->GetTextStyle(&display->textRuns[0].style); display->currentStyle->GetTextStyle(&display->textRuns[0].style);
display->textRuns[1].offset = stringBytes; display->textRuns[1].offset = stringBytes;
@ -4987,6 +5027,7 @@ void EsTextDisplaySetContents(EsTextDisplay *display, const char *string, ptrdif
EsTextDisplay *EsTextDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style, const char *label, ptrdiff_t labelBytes) { EsTextDisplay *EsTextDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style, const char *label, ptrdiff_t labelBytes) {
EsTextDisplay *display = (EsTextDisplay *) EsHeapAllocate(sizeof(EsTextDisplay), true); EsTextDisplay *display = (EsTextDisplay *) EsHeapAllocate(sizeof(EsTextDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessTextDisplayMessage, style ?: UIGetDefaultStyleVariant(ES_STYLE_TEXT_LABEL, parent)); display->Initialise(parent, flags, ProcessTextDisplayMessage, style ?: UIGetDefaultStyleVariant(ES_STYLE_TEXT_LABEL, parent));
display->cName = "text display"; display->cName = "text display";
if (labelBytes == -1) labelBytes = EsCStringLength(label); if (labelBytes == -1) labelBytes = EsCStringLength(label);
@ -5100,7 +5141,7 @@ int ProcessListDisplayMessage(EsElement *element, EsMessage *message) {
bounds.t += child->offsetY; bounds.t += child->offsetY;
bounds.b = bounds.t + child->height; bounds.b = bounds.t + child->height;
EsTextPlan *plan = EsTextPlanCreate(element, &properties, bounds, buffer, textRun, 1); EsTextPlan *plan = EsTextPlanCreate(element, &properties, bounds, buffer, textRun, 1);
EsDrawText(message->painter, plan, bounds); if (plan) EsDrawText(message->painter, plan, bounds);
bounds.t -= child->offsetY; bounds.t -= child->offsetY;
counter++; counter++;
} }
@ -5115,6 +5156,7 @@ int ProcessListDisplayMessage(EsElement *element, EsMessage *message) {
EsListDisplay *EsListDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style) { EsListDisplay *EsListDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsListDisplay *display = (EsListDisplay *) EsHeapAllocate(sizeof(EsListDisplay), true); EsListDisplay *display = (EsListDisplay *) EsHeapAllocate(sizeof(EsListDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessListDisplayMessage, style ?: ES_STYLE_LIST_DISPLAY_DEFAULT); display->Initialise(parent, flags, ProcessListDisplayMessage, style ?: ES_STYLE_LIST_DISPLAY_DEFAULT);
display->cName = "list display"; display->cName = "list display";
return display; return display;

View File

@ -2074,14 +2074,21 @@ void UIStyle::PaintText(EsPainter *painter, EsElement *element, EsRectangle rect
size_t textRunCount; size_t textRunCount;
EsRichTextParse(text, textBytes, &string, &textRuns, &textRunCount, &textRun[0].style); EsRichTextParse(text, textBytes, &string, &textRuns, &textRunCount, &textRun[0].style);
EsTextPlan *plan = EsTextPlanCreate(element, &properties, textBounds, string, textRuns, textRunCount); EsTextPlan *plan = EsTextPlanCreate(element, &properties, textBounds, string, textRuns, textRunCount);
EsDrawText(painter, plan, textBounds, nullptr, selectionProperties);
EsTextPlanDestroy(plan); if (plan) {
EsDrawText(painter, plan, textBounds, nullptr, selectionProperties);
EsTextPlanDestroy(plan);
}
EsHeapFree(textRuns); EsHeapFree(textRuns);
EsHeapFree(string); EsHeapFree(string);
} else { } else {
EsTextPlan *plan = EsTextPlanCreate(element, &properties, textBounds, text, textRun, 1); EsTextPlan *plan = EsTextPlanCreate(element, &properties, textBounds, text, textRun, 1);
PaintTextLayers(painter, plan, textBounds, selectionProperties);
EsTextPlanDestroy(plan); if (plan) {
PaintTextLayers(painter, plan, textBounds, selectionProperties);
EsTextPlanDestroy(plan);
}
} }
} }

View File

@ -328,8 +328,12 @@ ES_EXTERN_C ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALL
KernelPanic("AcpiOsExecute - Exceeded maximum event count, 256.\n"); KernelPanic("AcpiOsExecute - Exceeded maximum event count, 256.\n");
} }
acpiEvents[acpiEventCount++] = thread; if (thread) {
return AE_OK; acpiEvents[acpiEventCount++] = thread;
return AE_OK;
} else {
return AE_NO_MEMORY;
}
} }
ES_EXTERN_C void AcpiOsSleep(UINT64 ms) { ES_EXTERN_C void AcpiOsSleep(UINT64 ms) {

View File

@ -202,6 +202,7 @@ EsError KLoadELF(KNode *node, KLoadedExecutable *executable) {
if (header.instructionSet != 0x3E) return ES_ERROR_UNSUPPORTED_EXECUTABLE; if (header.instructionSet != 0x3E) return ES_ERROR_UNSUPPORTED_EXECUTABLE;
ElfProgramHeader *programHeaders = (ElfProgramHeader *) EsHeapAllocate(programHeaderEntrySize * header.programHeaderEntries, false, K_PAGED); ElfProgramHeader *programHeaders = (ElfProgramHeader *) EsHeapAllocate(programHeaderEntrySize * header.programHeaderEntries, false, K_PAGED);
if (!programHeaders) return ES_ERROR_INSUFFICIENT_RESOURCES;
EsDefer(EsHeapFree(programHeaders, 0, K_PAGED)); EsDefer(EsHeapFree(programHeaders, 0, K_PAGED));
bytesRead = FSFileReadSync(node, (uint8_t *) programHeaders, executableOffset + header.programHeaderTable, programHeaderEntrySize * header.programHeaderEntries, 0); bytesRead = FSFileReadSync(node, (uint8_t *) programHeaders, executableOffset + header.programHeaderTable, programHeaderEntrySize * header.programHeaderEntries, 0);

View File

@ -1182,7 +1182,7 @@ void FSNodeCloseHandle(KNode *node, uint32_t flags) {
// Spawn a thread to unmount it. // Spawn a thread to unmount it.
fileSystem->unmounting = true; fileSystem->unmounting = true;
__sync_fetch_and_add(&fs.fileSystemsUnmounting, 1); __sync_fetch_and_add(&fs.fileSystemsUnmounting, 1);
KThreadCreate("FSUnmount", FSUnmountFileSystem, (uintptr_t) fileSystem); KThreadCreate("FSUnmount", FSUnmountFileSystem, (uintptr_t) fileSystem); // TODO What should happen if creating the thread fails?
} }
if (deleted) { if (deleted) {
@ -1799,6 +1799,11 @@ void FSDetectFileSystem(KBlockDevice *device) {
} }
uint8_t *information = (uint8_t *) EsHeapAllocate(sectorsToRead * device->sectorSize, false, K_FIXED); uint8_t *information = (uint8_t *) EsHeapAllocate(sectorsToRead * device->sectorSize, false, K_FIXED);
if (!information) {
return;
}
device->information = information; device->information = information;
KDMABuffer dmaBuffer = { (uintptr_t) information }; KDMABuffer dmaBuffer = { (uintptr_t) information };

View File

@ -1982,16 +1982,12 @@ void *Pool::Add(size_t _elementSize) {
void *address; void *address;
#if 1
if (cacheEntries) { if (cacheEntries) {
address = cache[--cacheEntries]; address = cache[--cacheEntries];
EsMemoryZero(address, elementSize); EsMemoryZero(address, elementSize);
} else { } else {
address = EsHeapAllocate(elementSize, true, K_FIXED); address = EsHeapAllocate(elementSize, true, K_FIXED);
} }
#else
address = EsHeapAllocate(elementSize, true);
#endif
return address; return address;
} }

View File

@ -195,6 +195,10 @@ namespace POSIX {
KMutexAcquire(&threadPOSIXDataMutex); KMutexAcquire(&threadPOSIXDataMutex);
if (!currentThread->posixData) currentThread->posixData = (POSIXThread *) EsHeapAllocate(sizeof(POSIXThread), true, K_FIXED); if (!currentThread->posixData) currentThread->posixData = (POSIXThread *) EsHeapAllocate(sizeof(POSIXThread), true, K_FIXED);
KMutexRelease(&threadPOSIXDataMutex); KMutexRelease(&threadPOSIXDataMutex);
if (!currentThread->posixData) {
return -ENOMEM;
}
} }
if (currentThread->posixData->forkProcess) { if (currentThread->posixData->forkProcess) {
@ -260,7 +264,7 @@ namespace POSIX {
} }
file->path = (char *) EsHeapAllocate(pathLength + 1, true, K_FIXED); file->path = (char *) EsHeapAllocate(pathLength + 1, true, K_FIXED);
EsMemoryCopy(file->path, path, pathLength); if (file->path) EsMemoryCopy(file->path, path, pathLength);
if ((flags & O_TRUNC) && file->type == POSIX_FILE_NORMAL) { if ((flags & O_TRUNC) && file->type == POSIX_FILE_NORMAL) {
FSFileResize(file->node, 0); FSFileResize(file->node, 0);
@ -278,7 +282,7 @@ namespace POSIX {
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 2, true); SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 2, true);
KMutexAcquire(&file->mutex); KMutexAcquire(&file->mutex);
EsDefer(KMutexRelease(&file->mutex)); EsDefer(KMutexRelease(&file->mutex));
int length = EsCStringLength(file->path); int length = file->path ? EsCStringLength(file->path) : 0;
if (length > syscall.arguments[2]) length = syscall.arguments[2]; if (length > syscall.arguments[2]) length = syscall.arguments[2];
EsMemoryZero((void *) syscall.arguments[1], syscall.arguments[2]); EsMemoryZero((void *) syscall.arguments[1], syscall.arguments[2]);
EsMemoryCopy((void *) syscall.arguments[1], file->path, length); EsMemoryCopy((void *) syscall.arguments[1], file->path, length);

View File

@ -378,6 +378,7 @@ Thread *Scheduler::SpawnThread(const char *cName, uintptr_t startAddress, uintpt
if (terminating) return nullptr; if (terminating) return nullptr;
Thread *thread = (Thread *) threadPool.Add(sizeof(Thread)); Thread *thread = (Thread *) threadPool.Add(sizeof(Thread));
if (!thread) return nullptr;
KernelLog(LOG_INFO, "Scheduler", "spawn thread", "Created thread, %x to start at %x\n", thread, startAddress); KernelLog(LOG_INFO, "Scheduler", "spawn thread", "Created thread, %x to start at %x\n", thread, startAddress);
thread->isKernelThread = !userland; thread->isKernelThread = !userland;
thread->priority = (flags & SPAWN_THREAD_LOW_PRIORITY) ? THREAD_PRIORITY_LOW : THREAD_PRIORITY_NORMAL; thread->priority = (flags & SPAWN_THREAD_LOW_PRIORITY) ? THREAD_PRIORITY_LOW : THREAD_PRIORITY_NORMAL;

View File

@ -1454,6 +1454,11 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_SYSTEM_TAKE_SNAPSHOT) {
KSpinlockRelease(&scheduler.lock); KSpinlockRelease(&scheduler.lock);
buffer = EsHeapAllocate(bufferSize, true, K_FIXED); buffer = EsHeapAllocate(bufferSize, true, K_FIXED);
if (!buffer) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
}
EsMemoryZero(buffer, bufferSize); EsMemoryZero(buffer, bufferSize);
KSpinlockAcquire(&scheduler.lock); KSpinlockAcquire(&scheduler.lock);

View File

@ -880,6 +880,12 @@ char *EsStringAllocateAndFormatV(size_t *bytes, const char *format, va_list argu
if (bytes) *bytes = needed; if (bytes) *bytes = needed;
char *buffer = (char *) EsHeapAllocate(needed + 1, false); char *buffer = (char *) EsHeapAllocate(needed + 1, false);
if (!buffer) {
if (bytes) *bytes = 0;
return nullptr;
}
char *position = buffer; char *position = buffer;
buffer[needed] = 0; buffer[needed] = 0;
@ -1625,6 +1631,11 @@ size_t EsPathFindUniqueName(char *buffer, size_t originalBytes, size_t bufferByt
} }
char *buffer2 = (char *) EsHeapAllocate(bufferBytes, false); char *buffer2 = (char *) EsHeapAllocate(bufferBytes, false);
if (!buffer2) {
return 0;
}
EsDefer(EsHeapFree(buffer2)); EsDefer(EsHeapFree(buffer2));
uintptr_t attempt = 2; uintptr_t attempt = 2;

View File

@ -1524,6 +1524,10 @@ namespace Calculator {
if (!allocationPool) { if (!allocationPool) {
allocationPool = (char *) EsHeapAllocate(CALCULATOR_PARSER_ALLOCATION_POOL_SIZE, false); allocationPool = (char *) EsHeapAllocate(CALCULATOR_PARSER_ALLOCATION_POOL_SIZE, false);
if (!allocationPool) {
return nullptr;
}
} }
void *pointer = allocationPool + allocatedBytes; void *pointer = allocationPool + allocatedBytes;