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

View File

@ -394,17 +394,25 @@ struct ColorPickerHost {
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) {
EsHeapFree(*pointer);
}
if (!data && !bytes) {
*pointer = nullptr;
*outBytes = 0;
} else {
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,
const char *content, ptrdiff_t contentBytes, uint32_t iconID, uint32_t flags) {
EsElement *dialog = EsDialogShow(window);
if (!dialog) return nullptr;
EsPanel *heading = EsPanelCreate(dialog, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_DIALOG_HEADING);
if (!heading) return nullptr;
if (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";
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) {
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);
gui.allWindows.Add(window);
if (!window) return nullptr;
if (!gui.allWindows.Add(window)) {
EsHeapFree(window);
return nullptr;
}
window->instance = instance;
if (style == ES_WINDOW_NORMAL) {
@ -945,6 +962,7 @@ EsElement *EsMenuGetSource(EsMenu *menu) {
EsMenu *EsMenuCreate(EsElement *source, uint64_t flags) {
EsWindow *menu = (EsWindow *) EsWindowCreate(source->instance, ES_WINDOW_MENU);
if (!menu) return nullptr;
menu->flags |= flags;
menu->activated = true;
menu->source = source;
@ -1063,11 +1081,13 @@ void FileMenuCreate(EsInstance *_instance, EsElement *element, EsCommand *) {
APIInstance *instance = (APIInstance *) _instance->_private;
EsAssert(instance->instanceClass == ES_INSTANCE_CLASS_EDITOR);
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;
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?
// 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);
EsPanel *panel2 = EsPanelCreate(panel1, ES_FLAGS_DEFAULT, &styleFileMenuDocumentInformationPanel2);
if (!panel2) goto show;
EsPanel *panel3 = EsPanelCreate(panel2, ES_PANEL_HORIZONTAL | ES_PANEL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel3) goto show;
if (newDocument) {
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.
if (!renameButton) goto show;
EsButtonSetIcon(renameButton, ES_ICON_DOCUMENT_EDIT_SYMBOLIC);
if (!newDocument) {
EsPanel *panel4 = EsPanelCreate(panel2, ES_PANEL_TABLE | ES_PANEL_HORIZONTAL | ES_CELL_H_LEFT, &styleFileMenuDocumentInformationPanel2);
if (!panel4) goto show;
EsPanelSetBands(panel4, 2 /* columns */);
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(CommonFileVersionHistory)); // TODO.
EsMenuAddCommand(menu, ES_FLAGS_DEFAULT, INTERFACE_STRING(CommonFileShowInFileManager), &instance->commandShowInFileManager);
EsMenuShow(menu);
show: EsMenuShow(menu);
}
void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings) {
EsButton *button = EsButtonCreate(element, ES_BUTTON_DROPDOWN, 0, INTERFACE_STRING(CommonFileMenu));
if (!button) return;
button->accessKey = 'F';
button->userData = (void *) settings;
EsButtonOnCommand(button, FileMenuCreate);
@ -1651,7 +1677,7 @@ void EsElement::InternalPaint(EsPainter *painter, int paintFlags) {
bool EsElement::StartAnimating() {
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;
state |= UI_STATE_ANIMATING;
lastTimeStamp = 0;
@ -2703,6 +2729,7 @@ int ProcessScrollbarButtonMessage(EsElement *element, EsMessage *message) {
EsScrollbar *ScrollbarCreate(EsElement *parent, uint64_t flags) {
EsScrollbar *scrollbar = (EsScrollbar *) EsHeapAllocate(sizeof(EsScrollbar), true);
if (!scrollbar) return nullptr;
scrollbar->thumb = (EsElement *) EsHeapAllocate(sizeof(EsElement), true);
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++) {
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);
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]->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 (!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) {
EsElementDestroy(pad);
pad = nullptr;
@ -3333,6 +3368,7 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
EsPanel *EsPanelCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsPanel *panel = (EsPanel *) EsHeapAllocate(sizeof(EsPanel), true);
if (!panel) return nullptr;
panel->Initialise(parent, flags, ProcessPanelMessage, style);
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) {
EsSpacer *spacer = (EsSpacer *) EsHeapAllocate(sizeof(EsSpacer), true);
if (!spacer) return nullptr;
spacer->Initialise(panel, flags, ProcessSpacerMessage, style);
spacer->cName = "spacer";
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 *element = (EsElement *) EsHeapAllocate(sizeof(EsElement), true);
if (!element) return nullptr;
element->Initialise(parent, flags, nullptr, style);
element->cName = "custom element";
return element;
@ -3604,6 +3642,7 @@ int ProcessCanvasPaneMessage(EsElement *element, EsMessage *message) {
EsCanvasPane *EsCanvasPaneCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsCanvasPane *pane = (EsCanvasPane *) EsHeapAllocate(sizeof(EsCanvasPane), true);
if (!pane) return nullptr;
pane->Initialise(parent, flags, ProcessCanvasPaneMessage, style);
pane->cName = "canvas pane";
pane->zoom = 1.0;
@ -3659,12 +3698,12 @@ void EsAnnouncementShow(EsWindow *parent, uint64_t flags, int32_t x, int32_t y,
(void) flags;
EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_TIP);
if (!window) return;
window->messageUser = AnnouncementMessage;
EsTextDisplay *display = EsTextDisplayCreate(window, ES_CELL_FILL, ES_STYLE_ANNOUNCEMENT, text, textBytes);
int32_t width = display->GetWidth(0);
int32_t height = display->GetHeight(width);
int32_t width = display ? display->GetWidth(0) : 0;
int32_t height = display ? display->GetHeight(width) : 0;
EsRectangle parentBounds = {};
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 *button = (EsButton *) EsHeapAllocate(sizeof(EsButton), true);
if (!button) return button;
if (!style) {
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);
HeapDuplicate((void **) &button->label, label, labelBytes);
button->labelBytes = labelBytes;
HeapDuplicate((void **) &button->label, &button->labelBytes, label, labelBytes);
if ((flags & ES_BUTTON_MENU_ITEM) && (flags & ES_MENU_ITEM_HEADER)) {
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,
ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_MENU_ITEM | ES_CELL_H_FILL | flags, 0,
label, labelBytes != -1 ? labelBytes : EsCStringLength(label));
if (!button) return;
button->userData = (void *) callback;
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,
ES_BUTTON_NOT_FOCUSABLE | ES_BUTTON_MENU_ITEM | ES_CELL_H_FILL | flags,
0, label, labelBytes);
if (!button) return;
EsCommandAddButton(command, button);
}
@ -4131,6 +4172,7 @@ int ProcessColorChosenPointMessage(EsElement *element, EsMessage *message) {
void ColorPickerCreate(EsElement *parent, ColorPickerHost host, uint32_t initialColor, bool showTextbox) {
ColorPicker *picker = (ColorPicker *) EsHeapAllocate(sizeof(ColorPicker), true);
if (!picker) return;
picker->host = host;
picker->color = initialColor & 0xFFFFFF;
picker->opacity = (float) (initialColor >> 24) / 255.0f;
@ -4500,6 +4542,7 @@ int ProcessColorWellMessage(EsElement *element, EsMessage *message) {
DrawStyledBox(message->painter, box);
} else if (message->type == ES_MSG_MOUSE_LEFT_CLICK) {
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 };
ColorPickerCreate((EsElement *) menu, host, well->color, true);
EsMenuShow(menu);
@ -4512,6 +4555,7 @@ int ProcessColorWellMessage(EsElement *element, EsMessage *message) {
EsColorWell *EsColorWellCreate(EsElement *parent, uint64_t flags, uint32_t initialColor) {
EsColorWell *well = (EsColorWell *) EsHeapAllocate(sizeof(EsColorWell), true);
if (!well) return nullptr;
well->color = initialColor;
well->Initialise(parent, flags | ES_ELEMENT_FOCUSABLE, ProcessColorWellMessage, ES_STYLE_PUSH_BUTTON_NORMAL_COLOR_WELL);
well->cName = "color well";
@ -4706,6 +4750,11 @@ int ProcessSplitterMessage(EsElement *element, EsMessage *message) {
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.
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 *splitter = (EsSplitter *) EsHeapAllocate(sizeof(EsSplitter), true);
if (!splitter) return nullptr;
splitter->horizontal = flags & ES_SPLITTER_HORIZONTAL;
splitter->Initialise(parent, flags | ES_ELEMENT_NO_CLIP, ProcessSplitterMessage,
style ?: ES_STYLE_PANEL_WINDOW_BACKGROUND);
@ -4914,8 +4964,9 @@ int ProcessImageDisplayMessage(EsElement *element, EsMessage *message) {
}
if (~display->flags & UI_STATE_CHECK_VISIBLE) {
display->state |= UI_STATE_CHECK_VISIBLE;
display->window->checkVisible.Add(display);
if (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 *display = (EsImageDisplay *) EsHeapAllocate(sizeof(EsImageDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessImageDisplayMessage, style);
display->cName = "image";
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 *display = (EsIconDisplay *) EsHeapAllocate(sizeof(EsIconDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessIconDisplayMessage, style ?: ES_STYLE_ICON_DISPLAY);
display->cName = "icon";
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 *slider = (EsSlider *) EsHeapAllocate(sizeof(EsSlider), true);
if (!slider) return nullptr;
slider->Initialise(parent, flags | ES_ELEMENT_FOCUSABLE, ProcessSliderMessage, style ?: ES_STYLE_SLIDER_TRACK);
slider->cName = "slider";
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) {
bool first = !window->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";
EsAssert(window->toolbar->messageClass == ProcessPanelMessage);
@ -6099,8 +6158,9 @@ void AccessKeysGather(EsElement *element) {
entry.bounds = hintBounds;
gui.accessKeys.entries.Add(entry);
gui.accessKeys.numbers[entry.character - 'A']++;
if (gui.accessKeys.entries.Add(entry)) {
gui.accessKeys.numbers[entry.character - 'A']++;
}
}
void AccessKeyHintsShow(EsPainter *painter) {
@ -7071,8 +7131,7 @@ int InspectorContentTextboxCallback(EsElement *element, EsMessage *message) {
if (e->messageClass == ProcessButtonMessage) {
EsButton *button = (EsButton *) e;
HeapDuplicate((void **) &button->label, newContent, newContentBytes);
button->labelBytes = newContentBytes;
HeapDuplicate((void **) &button->label, &button->labelBytes, newContent, newContentBytes);
} else if (e->messageClass == ProcessTextDisplayMessage) {
EsTextDisplay *display = (EsTextDisplay *) e;
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,
const EsStyle *itemStyle, const EsStyle *headerItemStyle, const EsStyle *footerItemStyle) {
EsListView *view = (EsListView *) EsHeapAllocate(sizeof(EsListView), true);
if (!view) return nullptr;
view->primaryCellStyle = GetStyle(MakeStyleKey(ES_STYLE_LIST_PRIMARY_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 };
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.
@ -2339,8 +2343,7 @@ void EsListViewSelect(EsListView *view, EsListViewIndex group, EsListViewIndex i
void EsListViewSetEmptyMessage(EsListView *view, const char *message, ptrdiff_t messageBytes) {
EsMessageMutexCheck();
if (messageBytes == -1) messageBytes = EsCStringLength(message);
HeapDuplicate((void **) &view->emptyMessage, message, messageBytes);
view->emptyMessageBytes = messageBytes;
HeapDuplicate((void **) &view->emptyMessage, &view->emptyMessageBytes, message, messageBytes);
if (!view->totalItemCount) {
view->Repaint(true);
@ -2389,8 +2392,7 @@ EsListViewIndex EsListViewFixedItemInsert(EsListView *view, const char *string,
ListViewFixedItem item = {};
item.data = data;
item.iconID = iconID;
HeapDuplicate((void **) &item.firstColumn.string, string, stringBytes);
item.firstColumn.bytes = stringBytes;
HeapDuplicate((void **) &item.firstColumn.string, &item.firstColumn.bytes, string, stringBytes);
view->fixedItems.Insert(item, index);
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());
ListViewFixedString fixedString = {};
fixedString.bytes = stringBytes == -1 ? EsCStringLength(string) : stringBytes;
HeapDuplicate((void **) &fixedString, string, fixedString.bytes);
view->fixedItems[index].otherColumns.Add(fixedString);
EsListViewInvalidateContent(view, 0, index);
size_t outBytes;
HeapDuplicate((void **) &fixedString, &outBytes, string, fixedString.bytes);
if (outBytes == fixedString.bytes) {
view->fixedItems[index].otherColumns.Add(fixedString);
EsListViewInvalidateContent(view, 0, 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);
if (!view->inlineTextbox) {
return nullptr;
}
EsAssert(view->inlineTextbox->messageClass == ProcessTextboxMessage);
view->inlineTextbox->messageClass = ListViewInlineTextboxMessage;

View File

@ -187,12 +187,21 @@ void SettingsNumberBoxSetValue(EsElement *element, double newValueDouble) {
EsTextboxInsert(textbox, buffer, bytes);
EsMutexAcquire(&api.systemConfigurationMutex);
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true);
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
int32_t 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);
int32_t oldValue = 0;
if (group) {
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
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);
if (oldValue != newValue) {
@ -245,13 +254,22 @@ void SettingsCheckboxCommand(EsInstance *_instance, EsElement *element, EsComman
bool newValue = EsButtonGetCheck(button) == ES_CHECK_CHECKED;
EsMutexAcquire(&api.systemConfigurationMutex);
EsSystemConfigurationGroup *group = SystemConfigurationGetGroup(control->cConfigurationSection, -1, true);
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
bool oldValue = EsIntegerParse(item->value, item->valueBytes);
EsHeapFree(item->value);
item->value = (char *) EsHeapAllocate(2, true);
*item->value = newValue ? '1' : '0';
item->valueBytes = 1;
bool oldValue;
if (group) {
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
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);
if (oldValue == newValue) return;
@ -362,13 +380,22 @@ int SettingsSliderMessage(EsElement *element, EsMessage *message) {
if (message->type == ES_MSG_SLIDER_MOVED && !message->sliderMoved.inDrag) {
EsMutexAcquire(&api.systemConfigurationMutex);
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 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);
if (group) {
EsSystemConfigurationItem *item = SystemConfigurationGetItem(group, control->cConfigurationKey, -1, true);
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);
if (oldValue != newValue) {

View File

@ -800,6 +800,7 @@ EsFileStore *EsClipboardOpen(EsClipboard clipboard) {
EsBufferReadInto(&buffer, &error, sizeof(error));
EsHeapFree(buffer.out);
EsFileStore *fileStore = FileStoreCreateFromHandle(file);
if (!fileStore) return nullptr;
fileStore->error = error;
return fileStore;
}
@ -823,8 +824,13 @@ EsError EsClipboardCloseAndAdd(EsClipboard clipboard, EsClipboardFormat format,
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);
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) {

View File

@ -557,10 +557,7 @@ bool EsFontDatabaseLookupByID(EsFontFamily id, EsFontInformation *information) {
EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFileStore *store) {
FontInitialise();
EsAssert(store->handles);
store->handles++;
FontDatabaseEntry *entry = nullptr;
if (information->nameBytes) {
@ -586,12 +583,18 @@ EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFi
FontDatabaseEntry e = {};
EsMemoryCopy(&e, information, sizeof(EsFontInformation));
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:;
store->handles++;
entry->availableWeightsNormal |= information->availableWeightsNormal;
entry->availableWeightsItalic |= information->availableWeightsItalic;
@ -1846,13 +1849,13 @@ void TextAddEllipsis(EsTextPlan *plan, int32_t maximumLineWidth, bool needFinalE
TextPiece piece = {};
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;
for (uintptr_t i = 0; i < glyphCount; i++) {
plan->glyphInfos.Add(glyphInfos[i]);
plan->glyphPositions.Add(glyphPositions[i]);
if (!plan->glyphInfos.Add(glyphInfos[i])) break;
if (!plan->glyphPositions.Add(glyphPositions[i])) break;
piece.glyphCount++;
int32_t width = glyphPositions[i].x_advance;
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);
addedWidth += piece->width;
piece->glyphOffset = plan->glyphInfos.Length();
piece->glyphCount = piece->end - piece->start;
piece->glyphCount = 0;
piece->ascent = FontGetAscent(&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 = {};
info.cluster = piece->start + i;
info.codepoint = 0xFFFFFFFF;
hb_glyph_position_t position = {};
position.x_advance = i ? tabWidth : firstWidth;
plan->glyphInfos.Add(info);
plan->glyphPositions.Add(position);
if (!plan->glyphInfos.Add(info)) break;
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') {
TextPiece _piece = {};
plan->pieces.Add(_piece);
TextPiece *piece = &plan->pieces.Last();
piece->style = plan->currentTextStyle;
piece->glyphOffset = 0;
piece->glyphCount = 0;
piece->start = start;
piece->end = end;
piece->isTabPiece = true;
if (plan->pieces.Add(_piece)) {
TextPiece *piece = &plan->pieces.Last();
piece->style = plan->currentTextStyle;
piece->glyphOffset = 0;
piece->glyphCount = 0;
piece->start = start;
piece->end = end;
piece->isTabPiece = true;
}
plan->textRunPosition++;
continue;
}
@ -2041,31 +2048,34 @@ int32_t TextBuildTextPieces(EsTextPlan *plan, uintptr_t sectionStart, uintptr_t
// Create the text 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++) {
plan->glyphInfos.Add(glyphInfos[i]);
plan->glyphPositions.Add(glyphPositions[i]);
if (plan->pieces.Add(_piece)) {
TextPiece *piece = &plan->pieces.Last();
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 += plan->currentTextStyle->tracking * FREETYPE_UNIT_SCALE;
piece->width += glyphPositions[i].x_advance;
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.
plan->textRunPosition++;
@ -2115,7 +2125,10 @@ EsTextPlan *EsTextPlanCreate(EsElement *element, EsTextPlanProperties *propertie
plan.properties = *properties;
TextLine blankLine = {};
plan.lines.Add(blankLine);
if (!plan.lines.Add(blankLine)) {
return nullptr;
}
// Setup the HarfBuzz buffer.
@ -2166,8 +2179,9 @@ EsTextPlan *EsTextPlanCreate(EsElement *element, EsTextPlanProperties *propertie
break;
}
plan.lines.Add(blankLine);
plan.lines.Last().pieceOffset = pieceOffset;
if (plan.lines.Add(blankLine)) {
plan.lines.Last().pieceOffset = pieceOffset;
}
}
#if 0
@ -3980,7 +3994,14 @@ char *EsTextboxGetContents(EsTextbox *textbox, size_t *_bytes, uint32_t flags) {
buffer[position] = 0;
EsAssert(position <= bytes);
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) {
@ -4210,7 +4231,8 @@ int ProcessTextboxMarginMessage(EsElement *element, EsMessage *message) {
textRun[1].offset = EsStringFormat(label, sizeof(label), "%d", i + textbox->firstVisibleLine + 1);
EsTextPlanProperties properties = {};
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;
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);
} else {
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) {
textbox->inRightClickDrag = false;
EsMenu *menu = EsMenuCreate(textbox, ES_MENU_AT_CURSOR);
if (!menu) return ES_HANDLED;
// 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 *textbox = (EsTextbox *) EsHeapAllocate(sizeof(EsTextbox), true);
if (!textbox) return nullptr;
if (!style) {
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);
textbox->overlayData = panel;
if (!panel) {
return;
}
uint8_t _buffer[256];
EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) };
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,
ES_STYLE_BREADCRUMB_BAR_CRUMB, (char *) buffer.out, buffer.position);
crumb->userData = m.getBreadcrumb.index;
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;
}
if (crumb) {
crumb->userData = m.getBreadcrumb.index;
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++;
}
@ -4954,7 +4987,14 @@ void EsTextDisplaySetStyledContents(EsTextDisplay *display, const char *string,
display->textRuns = (EsTextRun *) EsHeapAllocate(sizeof(EsTextRun) * (runCount + 1), true);
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));
display->usingSyntaxHighlighting = false;
@ -4973,7 +5013,7 @@ void EsTextDisplaySetContents(EsTextDisplay *display, const char *string, ptrdif
display->currentStyle->GetTextStyle(&baseStyle);
EsRichTextParse(string, stringBytes, &display->contents, &display->textRuns, &display->textRunCount, &baseStyle);
} 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->currentStyle->GetTextStyle(&display->textRuns[0].style);
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 *display = (EsTextDisplay *) EsHeapAllocate(sizeof(EsTextDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessTextDisplayMessage, style ?: UIGetDefaultStyleVariant(ES_STYLE_TEXT_LABEL, parent));
display->cName = "text display";
if (labelBytes == -1) labelBytes = EsCStringLength(label);
@ -5100,7 +5141,7 @@ int ProcessListDisplayMessage(EsElement *element, EsMessage *message) {
bounds.t += child->offsetY;
bounds.b = bounds.t + child->height;
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;
counter++;
}
@ -5115,6 +5156,7 @@ int ProcessListDisplayMessage(EsElement *element, EsMessage *message) {
EsListDisplay *EsListDisplayCreate(EsElement *parent, uint64_t flags, const EsStyle *style) {
EsListDisplay *display = (EsListDisplay *) EsHeapAllocate(sizeof(EsListDisplay), true);
if (!display) return nullptr;
display->Initialise(parent, flags, ProcessListDisplayMessage, style ?: ES_STYLE_LIST_DISPLAY_DEFAULT);
display->cName = "list display";
return display;

View File

@ -2074,14 +2074,21 @@ void UIStyle::PaintText(EsPainter *painter, EsElement *element, EsRectangle rect
size_t textRunCount;
EsRichTextParse(text, textBytes, &string, &textRuns, &textRunCount, &textRun[0].style);
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(string);
} else {
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");
}
acpiEvents[acpiEventCount++] = thread;
return AE_OK;
if (thread) {
acpiEvents[acpiEventCount++] = thread;
return AE_OK;
} else {
return AE_NO_MEMORY;
}
}
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;
ElfProgramHeader *programHeaders = (ElfProgramHeader *) EsHeapAllocate(programHeaderEntrySize * header.programHeaderEntries, false, K_PAGED);
if (!programHeaders) return ES_ERROR_INSUFFICIENT_RESOURCES;
EsDefer(EsHeapFree(programHeaders, 0, K_PAGED));
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.
fileSystem->unmounting = true;
__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) {
@ -1799,6 +1799,11 @@ void FSDetectFileSystem(KBlockDevice *device) {
}
uint8_t *information = (uint8_t *) EsHeapAllocate(sectorsToRead * device->sectorSize, false, K_FIXED);
if (!information) {
return;
}
device->information = information;
KDMABuffer dmaBuffer = { (uintptr_t) information };

View File

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

View File

@ -195,6 +195,10 @@ namespace POSIX {
KMutexAcquire(&threadPOSIXDataMutex);
if (!currentThread->posixData) currentThread->posixData = (POSIXThread *) EsHeapAllocate(sizeof(POSIXThread), true, K_FIXED);
KMutexRelease(&threadPOSIXDataMutex);
if (!currentThread->posixData) {
return -ENOMEM;
}
}
if (currentThread->posixData->forkProcess) {
@ -260,7 +264,7 @@ namespace POSIX {
}
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) {
FSFileResize(file->node, 0);
@ -278,7 +282,7 @@ namespace POSIX {
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 2, true);
KMutexAcquire(&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];
EsMemoryZero((void *) syscall.arguments[1], syscall.arguments[2]);
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;
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);
thread->isKernelThread = !userland;
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);
buffer = EsHeapAllocate(bufferSize, true, K_FIXED);
if (!buffer) {
SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
}
EsMemoryZero(buffer, bufferSize);
KSpinlockAcquire(&scheduler.lock);

View File

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

View File

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