mirror of https://gitlab.com/nakst/essence
saving images from image editor; auto update thumbnails in file manager
This commit is contained in:
parent
b4dfe96d85
commit
9a7c7106f4
|
@ -355,14 +355,19 @@ void FolderDetachInstance(Instance *instance) {
|
|||
folder->referenceCount--;
|
||||
|
||||
if (!folder->referenceCount) {
|
||||
EsAssert(!folder->attachedInstances.Length());
|
||||
foldersWithNoAttachedInstances.Add(folder);
|
||||
if (folder->refreshing) {
|
||||
loadedFolders.FindAndDeleteSwap(folder, true);
|
||||
FolderDestroy(folder);
|
||||
} else {
|
||||
EsAssert(!folder->attachedInstances.Length());
|
||||
foldersWithNoAttachedInstances.Add(folder);
|
||||
|
||||
if (foldersWithNoAttachedInstances.Length() > MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES) {
|
||||
Folder *leastRecentlyUsed = foldersWithNoAttachedInstances[0];
|
||||
loadedFolders.FindAndDeleteSwap(leastRecentlyUsed, true);
|
||||
foldersWithNoAttachedInstances.Delete(0);
|
||||
FolderDestroy(leastRecentlyUsed);
|
||||
if (foldersWithNoAttachedInstances.Length() > MAXIMUM_FOLDERS_WITH_NO_ATTACHED_INSTANCES) {
|
||||
Folder *leastRecentlyUsed = foldersWithNoAttachedInstances[0];
|
||||
loadedFolders.FindAndDeleteSwap(leastRecentlyUsed, true);
|
||||
foldersWithNoAttachedInstances.Delete(0);
|
||||
FolderDestroy(leastRecentlyUsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -419,6 +424,8 @@ void FolderAddEntryAndUpdateInstances(Folder *folder, const char *name, size_t n
|
|||
FolderEntry *entry = FolderAddEntry(folder, name, nameBytes, information, id);
|
||||
ListEntry listEntry = { .entry = entry };
|
||||
|
||||
ThumbnailGenerateIfNeeded(folder, entry, false, true /* modified */);
|
||||
|
||||
for (uintptr_t i = 0; i < folder->attachedInstances.Length(); i++) {
|
||||
Instance *instance = folder->attachedInstances[i];
|
||||
listEntry.selected = instance == selectItem;
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
#define ES_INSTANCE_TYPE Instance
|
||||
#include <essence.h>
|
||||
#include <shared/strings.cpp>
|
||||
|
||||
#include <shared/hash_table.cpp>
|
||||
#include <shared/array.cpp>
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/array.cpp>
|
||||
#undef IMPLEMENTATION
|
||||
|
||||
// TODO Possible candidates for moving in the core API:
|
||||
// - String/paths utils
|
||||
|
@ -239,6 +235,7 @@ void ListItemCreated(EsElement *element, uintptr_t index, bool fromFolderRename)
|
|||
FolderEntry *FolderAddEntry(Folder *folder, const char *_name, size_t nameBytes, EsDirectoryChild *information, uint64_t id = 0);
|
||||
void FolderAddEntries(Folder *folder, EsDirectoryChild *buffer, size_t entryCount);
|
||||
uint32_t NamespaceDefaultGetFileType(String);
|
||||
void ThumbnailGenerateIfNeeded(Folder *folder, FolderEntry *entry, bool fromFolderRename, bool modified);
|
||||
|
||||
Array<Drive> drives;
|
||||
EsMutex drivesMutex;
|
||||
|
|
|
@ -545,7 +545,7 @@ void ThumbnailResize(uint32_t *bits, uint32_t originalWidth, uint32_t originalHe
|
|||
}
|
||||
}
|
||||
|
||||
void ListItemGenerateThumbnailTask(Instance *, Task *task) {
|
||||
void ThumbnailGenerateTask(Instance *, Task *task) {
|
||||
EsMessageMutexAcquire();
|
||||
Thumbnail *thumbnail = thumbnailCache.Get(&task->id);
|
||||
bool cancelTask = !thumbnail || thumbnail->referenceCount == 0;
|
||||
|
@ -619,7 +619,7 @@ void ListItemGenerateThumbnailTask(Instance *, Task *task) {
|
|||
EsMessageMutexRelease();
|
||||
}
|
||||
|
||||
void ListItemGenerateThumbnailTaskComplete(Instance *, Task *task) {
|
||||
void ThumbnailGenerateTaskComplete(Instance *, Task *task) {
|
||||
Thumbnail *thumbnail = thumbnailCache.Get(&task->id);
|
||||
|
||||
if (thumbnail) {
|
||||
|
@ -637,11 +637,47 @@ void ListItemGenerateThumbnailTaskComplete(Instance *, Task *task) {
|
|||
StringDestroy(&task->string);
|
||||
}
|
||||
|
||||
Thumbnail *ListItemGetThumbnail(EsElement *element) {
|
||||
Instance *instance = element->instance;
|
||||
ListEntry *entry = &instance->listContents[EsListViewGetIndexFromItem(element)];
|
||||
Thumbnail *thumbnail = thumbnailCache.Get(&entry->entry->id);
|
||||
return thumbnail;
|
||||
void ThumbnailGenerateIfNeeded(Folder *folder, FolderEntry *entry, bool fromFolderRename, bool modified) {
|
||||
FileType *fileType = FolderEntryGetType(folder, entry);
|
||||
|
||||
if (!fileType->hasThumbnailGenerator) {
|
||||
return; // The file type does not support thumbnail generation.
|
||||
}
|
||||
|
||||
Thumbnail *thumbnail;
|
||||
|
||||
// TODO Remove from LRU if needed.
|
||||
|
||||
if (modified) {
|
||||
thumbnail = thumbnailCache.Get(&entry->id);
|
||||
|
||||
if (!thumbnail || (!thumbnail->generatingTasksInProgress && !thumbnail->bits)) {
|
||||
return; // The thumbnail is not in use.
|
||||
}
|
||||
} else {
|
||||
thumbnail = thumbnailCache.Put(&entry->id);
|
||||
|
||||
if (!fromFolderRename) {
|
||||
thumbnail->referenceCount++;
|
||||
}
|
||||
|
||||
if ((thumbnail->generatingTasksInProgress && !fromFolderRename) || thumbnail->bits) {
|
||||
return; // The thumbnail is already being/has already been generated.
|
||||
}
|
||||
}
|
||||
|
||||
thumbnail->generatingTasksInProgress++;
|
||||
|
||||
String path = StringAllocateAndFormat("%s%s", STRFMT(folder->path), STRFMT(entry->GetInternalName()));
|
||||
|
||||
Task task = {
|
||||
.string = path,
|
||||
.id = entry->id,
|
||||
.callback = ThumbnailGenerateTask,
|
||||
.then = ThumbnailGenerateTaskComplete,
|
||||
};
|
||||
|
||||
NonBlockingTaskQueue(task);
|
||||
}
|
||||
|
||||
void ListItemCreated(EsElement *element, uintptr_t index, bool fromFolderRename) {
|
||||
|
@ -651,38 +687,14 @@ void ListItemCreated(EsElement *element, uintptr_t index, bool fromFolderRename)
|
|||
return; // The current view does not display thumbnails.
|
||||
}
|
||||
|
||||
ListEntry *listEntry = &instance->listContents[index];
|
||||
FolderEntry *entry = listEntry->entry;
|
||||
FileType *fileType = FolderEntryGetType(instance->folder, entry);
|
||||
ThumbnailGenerateIfNeeded(instance->folder, instance->listContents[index].entry, fromFolderRename, false /* not modified */);
|
||||
}
|
||||
|
||||
if (!fileType->hasThumbnailGenerator) {
|
||||
return; // The file type does not support thumbnail generation.
|
||||
}
|
||||
|
||||
Thumbnail *thumbnail = thumbnailCache.Put(&entry->id);
|
||||
|
||||
if (!fromFolderRename) {
|
||||
thumbnail->referenceCount++;
|
||||
}
|
||||
|
||||
// TODO Remove from LRU if needed.
|
||||
|
||||
if ((thumbnail->generatingTasksInProgress && !fromFolderRename) || thumbnail->bits) {
|
||||
return; // The thumbnail is already being/has already been generated.
|
||||
}
|
||||
|
||||
thumbnail->generatingTasksInProgress++;
|
||||
|
||||
String path = StringAllocateAndFormat("%s%s", STRFMT(instance->path), STRFMT(entry->GetInternalName()));
|
||||
|
||||
Task task = {
|
||||
.string = path,
|
||||
.id = entry->id,
|
||||
.callback = ListItemGenerateThumbnailTask,
|
||||
.then = ListItemGenerateThumbnailTaskComplete,
|
||||
};
|
||||
|
||||
NonBlockingTaskQueue(task);
|
||||
Thumbnail *ListItemGetThumbnail(EsElement *element) {
|
||||
Instance *instance = element->instance;
|
||||
ListEntry *entry = &instance->listContents[EsListViewGetIndexFromItem(element)];
|
||||
Thumbnail *thumbnail = thumbnailCache.Get(&entry->entry->id);
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
int ListItemMessage(EsElement *element, EsMessage *message) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#define ES_INSTANCE_TYPE Instance
|
||||
#include <essence.h>
|
||||
#include <shared/array.cpp>
|
||||
#include <shared/strings.cpp>
|
||||
|
||||
// TODO Previewing font files from the database.
|
||||
// TODO Installing fonts.
|
||||
|
@ -7,11 +9,6 @@
|
|||
// TODO Searching/filtering fonts.
|
||||
// TODO Single instance.
|
||||
|
||||
#include <shared/array.cpp>
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/array.cpp>
|
||||
#include <shared/strings.cpp>
|
||||
|
||||
#define SETTINGS_FILE "|Settings:/Default.ini"
|
||||
|
||||
struct Instance : EsInstance {
|
||||
|
|
|
@ -15,14 +15,17 @@
|
|||
|
||||
#define ES_INSTANCE_TYPE Instance
|
||||
#include <essence.h>
|
||||
|
||||
#include <shared/array.cpp>
|
||||
#include <shared/strings.cpp>
|
||||
|
||||
#ifdef OS_ESSENCE
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/array.cpp>
|
||||
#endif
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#define STBI_WRITE_NO_STDIO
|
||||
#define STBIW_MEMMOVE EsCRTmemmove
|
||||
#define STBIW_MALLOC(sz) EsCRTmalloc(sz)
|
||||
#define STBIW_REALLOC(p,newsz) EsCRTrealloc(p,newsz)
|
||||
#define STBIW_FREE(p) EsCRTfree(p)
|
||||
#define STBIW_ASSERT EsAssert
|
||||
#include <shared/stb_image_write.h>
|
||||
|
||||
#define TILE_SIZE (128)
|
||||
|
||||
|
@ -65,6 +68,12 @@ struct Instance : EsInstance {
|
|||
bool dragged;
|
||||
};
|
||||
|
||||
const EsInstanceClassEditorSettings editorSettings = {
|
||||
INTERFACE_STRING(ImageEditorNewFileName),
|
||||
INTERFACE_STRING(ImageEditorNewDocument),
|
||||
ES_ICON_IMAGE_X_GENERIC,
|
||||
};
|
||||
|
||||
const EsStyle styleBitmapSizeTextbox = {
|
||||
.inherit = ES_STYLE_TEXTBOX_BORDERED_SINGLE_COMPACT,
|
||||
|
||||
|
@ -433,7 +442,7 @@ int CanvasMessage(EsElement *element, EsMessage *message) {
|
|||
EsRectangle rectangle = instance->modifiedBounds;
|
||||
rectangle.l += painter->offsetX, rectangle.r += painter->offsetX;
|
||||
rectangle.t += painter->offsetY, rectangle.b += painter->offsetY;
|
||||
EsDrawBlock(painter, rectangle, 0xFF000000 | EsColorWellGetRGB(instance->colorWell));
|
||||
EsDrawBlock(painter, EsRectangleIntersection(rectangle, area), 0xFF000000 | EsColorWellGetRGB(instance->colorWell));
|
||||
}
|
||||
} else if ((message->type == ES_MSG_MOUSE_LEFT_DRAG || message->type == ES_MSG_MOUSE_MOVED)
|
||||
&& EsMouseIsLeftHeld() && instance->commandBrush.check == ES_CHECK_CHECKED) {
|
||||
|
@ -691,6 +700,7 @@ void MenuImage(Instance *instance, EsElement *element, EsCommand *) {
|
|||
void InstanceCreate(EsMessage *message) {
|
||||
Instance *instance = EsInstanceCreate(message, INTERFACE_STRING(ImageEditorTitle));
|
||||
EsElement *toolbar = EsWindowGetToolbar(instance->window);
|
||||
EsInstanceSetClassEditor(instance, &editorSettings);
|
||||
|
||||
// Register commands.
|
||||
|
||||
|
@ -706,6 +716,7 @@ void InstanceCreate(EsMessage *message) {
|
|||
|
||||
EsButton *button;
|
||||
|
||||
EsToolbarAddFileMenu(toolbar);
|
||||
button = EsButtonCreate(toolbar, ES_BUTTON_DROPDOWN, ES_STYLE_PUSH_BUTTON_TOOLBAR_BIG, INTERFACE_STRING(ImageEditorImage));
|
||||
EsButtonSetIcon(button, ES_ICON_IMAGE_X_GENERIC);
|
||||
button->accessKey = 'I';
|
||||
|
@ -755,7 +766,7 @@ void InstanceCreate(EsMessage *message) {
|
|||
|
||||
EsPanel *section = EsPanelCreate(toolbar, ES_PANEL_HORIZONTAL);
|
||||
EsTextDisplayCreate(section, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(ImageEditorPropertyColor));
|
||||
instance->colorWell = EsColorWellCreate(section, ES_FLAGS_DEFAULT, 0);
|
||||
instance->colorWell = EsColorWellCreate(section, ES_FLAGS_DEFAULT, 0xFFFF0000);
|
||||
instance->colorWell->accessKey = 'C';
|
||||
EsSpacerCreate(toolbar, ES_FLAGS_DEFAULT, 0, 5, 0);
|
||||
|
||||
|
@ -790,7 +801,22 @@ void InstanceCreate(EsMessage *message) {
|
|||
ImageCopyFromPaintTarget(instance, &instance->image, painter.clip);
|
||||
}
|
||||
|
||||
void WriteCallback(void *context, void *data, int size) {
|
||||
EsBufferWrite((EsBuffer *) context, data, size);
|
||||
}
|
||||
|
||||
void SwapRedAndBlueChannels(uint32_t *bits, size_t width, size_t height, size_t stride) {
|
||||
for (uintptr_t i = 0; i < height; i++) {
|
||||
for (uintptr_t j = 0; j < width; j++) {
|
||||
uint32_t *pixel = &bits[i * stride / 4 + j];
|
||||
*pixel = (*pixel & 0xFF00FF00) | (((*pixel >> 16) | (*pixel << 16)) & 0x00FF00FF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _start() {
|
||||
_init();
|
||||
|
||||
while (true) {
|
||||
EsMessage *message = EsMessageReceive();
|
||||
|
||||
|
@ -831,6 +857,47 @@ void _start() {
|
|||
|
||||
EsHeapFree(bits);
|
||||
EsInstanceOpenComplete(message, true);
|
||||
} else if (message->type == ES_MSG_INSTANCE_SAVE) {
|
||||
Instance *instance = message->instanceSave.instance;
|
||||
|
||||
uintptr_t extensionOffset = message->instanceSave.nameBytes;
|
||||
|
||||
while (extensionOffset) {
|
||||
if (message->instanceSave.name[extensionOffset - 1] == '.') {
|
||||
break;
|
||||
} else {
|
||||
extensionOffset--;
|
||||
}
|
||||
}
|
||||
|
||||
const char *extension = extensionOffset ? message->instanceSave.name + extensionOffset : "png";
|
||||
size_t extensionBytes = extensionOffset ? message->instanceSave.nameBytes - extensionOffset : 3;
|
||||
|
||||
uint32_t *bits;
|
||||
size_t width, height, stride;
|
||||
EsPaintTargetStartDirectAccess(instance->bitmap, &bits, &width, &height, &stride);
|
||||
EsAssert(stride == width * 4); // TODO Other strides.
|
||||
SwapRedAndBlueChannels(bits, width, height, stride); // stbi_write uses the other order. We swap back below.
|
||||
|
||||
uint8_t _buffer[4096];
|
||||
EsBuffer buffer = { .out = _buffer, .bytes = sizeof(_buffer) };
|
||||
buffer.fileStore = message->instanceSave.file;
|
||||
|
||||
if (0 == EsStringCompare(extension, extensionBytes, EsLiteral("jpg"))
|
||||
|| 0 == EsStringCompare(extension, extensionBytes, EsLiteral("jpeg"))) {
|
||||
stbi_write_jpg_to_func(WriteCallback, &buffer, width, height, 4, bits, 90);
|
||||
} else if (0 == EsStringCompare(extension, extensionBytes, EsLiteral("bmp"))) {
|
||||
stbi_write_bmp_to_func(WriteCallback, &buffer, width, height, 4, bits);
|
||||
} else if (0 == EsStringCompare(extension, extensionBytes, EsLiteral("tga"))) {
|
||||
stbi_write_tga_to_func(WriteCallback, &buffer, width, height, 4, bits);
|
||||
} else {
|
||||
stbi_write_png_to_func(WriteCallback, &buffer, width, height, 4, bits, stride);
|
||||
}
|
||||
|
||||
SwapRedAndBlueChannels(bits, width, height, stride); // Swap back.
|
||||
EsBufferFlushToFileStore(&buffer);
|
||||
EsPaintTargetEndDirectAccess(instance->bitmap);
|
||||
EsInstanceSaveComplete(message, true);
|
||||
} else if (message->type == ES_MSG_INSTANCE_DESTROY) {
|
||||
Instance *instance = message->instanceDestroy.instance;
|
||||
EsPaintTargetDestroy(instance->bitmap);
|
||||
|
|
|
@ -11,13 +11,9 @@
|
|||
#include <shared/hash.cpp>
|
||||
#include <shared/strings.cpp>
|
||||
#include <shared/partitions.cpp>
|
||||
#include <shared/array.cpp>
|
||||
#include <ports/lzma/LzmaDec.c>
|
||||
|
||||
#include <shared/array.cpp>
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/array.cpp>
|
||||
#undef IMPLEMENTATION
|
||||
|
||||
#define Log(...)
|
||||
// TODO Error handling.
|
||||
#define exit(x) EsAssert(false)
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#define ES_INSTANCE_TYPE Instance
|
||||
#include <essence.h>
|
||||
|
||||
#include <shared/strings.cpp>
|
||||
#include <shared/array.cpp>
|
||||
#include <ports/md4c/md4c.c>
|
||||
|
||||
#include <shared/array.cpp>
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/array.cpp>
|
||||
#undef IMPLEMENTATION
|
||||
|
||||
// TODO Inline code background?
|
||||
|
||||
// TODO When resizing the window, maintain the scroll position.
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
#define ES_INSTANCE_TYPE Instance
|
||||
#include <essence.h>
|
||||
|
||||
#include <shared/array.cpp>
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/array.cpp>
|
||||
#undef IMPLEMENTATION
|
||||
|
||||
// TODO Single instance.
|
||||
// TODO Sorting lists.
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
|
||||
#ifdef USE_STB_IMAGE
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_MALLOC(sz) EsCRTmalloc(sz)
|
||||
#define STBI_REALLOC(p,newsz) EsCRTrealloc(p,newsz)
|
||||
#define STBI_FREE(p) EsCRTfree(p)
|
||||
#define STBI_MALLOC(sz) EsCRTmalloc(sz)
|
||||
#define STBI_REALLOC(p,newsz) EsCRTrealloc(p,newsz)
|
||||
#define STBI_FREE(p) EsCRTfree(p)
|
||||
#define STBI_ASSERT(x) EsAssert(x)
|
||||
#define STBI_NO_STDIO
|
||||
#define STBI_ONLY_PNG
|
||||
#define STBI_ONLY_JPEG
|
||||
|
@ -37,10 +38,6 @@
|
|||
#include <shared/strings.cpp>
|
||||
#include <shared/common.cpp>
|
||||
|
||||
#define IMPLEMENTATION
|
||||
#include <shared/array.cpp>
|
||||
#undef IMPLEMENTATION
|
||||
|
||||
struct EnumString { const char *cName; int value; };
|
||||
#include <bin/enum_strings_array.h>
|
||||
|
||||
|
@ -970,6 +967,10 @@ EsMessage *EsMessageReceive() {
|
|||
m.instanceSave.file->handles = 1;
|
||||
m.instanceSave.instance = InstanceFromWindowID(message.message.tabOperation.id);
|
||||
|
||||
APIInstance *instance = (APIInstance *) m.instanceSave.instance->_private;
|
||||
m.instanceSave.name = instance->startupInformation->filePath;
|
||||
m.instanceSave.nameBytes = instance->startupInformation->filePathBytes;
|
||||
|
||||
if (m.instanceSave.file->error == ES_SUCCESS) {
|
||||
EsMemoryCopy(&message.message, &m, sizeof(EsMessage));
|
||||
return &message.message;
|
||||
|
|
|
@ -2521,14 +2521,18 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
char *oldPath = EsStringAllocateAndFormat(&oldPathBytes, "%s", document->pathBytes, document->path);
|
||||
char *newPath = EsStringAllocateAndFormat(&newPathBytes, "%s/%s", folderBytes, document->path, newNameBytes, newName);
|
||||
|
||||
EsMessage m = {};
|
||||
m.type = ES_MSG_INSTANCE_RENAME_RESPONSE;
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
m.tabOperation.error = EsPathMove(oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
if (oldPathBytes == newPathBytes && 0 == EsMemoryCompare(oldPath, newPath, oldPathBytes)) {
|
||||
// Same name.
|
||||
} else {
|
||||
EsMessage m = {};
|
||||
m.type = ES_MSG_INSTANCE_RENAME_RESPONSE;
|
||||
m.tabOperation.id = instance->embeddedWindowID;
|
||||
m.tabOperation.error = EsPathMove(oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
EsMessagePostRemote(instance->process->handle, &m);
|
||||
|
||||
if (m.tabOperation.error == ES_SUCCESS) {
|
||||
InstanceAnnouncePathMoved(nullptr, oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
if (m.tabOperation.error == ES_SUCCESS) {
|
||||
InstanceAnnouncePathMoved(nullptr, oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
}
|
||||
}
|
||||
|
||||
EsHeapFree(oldPath);
|
||||
|
|
|
@ -5174,7 +5174,7 @@ int FileMenuNameTextboxMessage(EsElement *element, EsMessage *message) {
|
|||
if (message->type == ES_MSG_TEXTBOX_EDIT_END) {
|
||||
APIInstance *instance = (APIInstance *) element->instance->_private;
|
||||
|
||||
if (!message->endEdit.rejected) {
|
||||
if (!message->endEdit.rejected && !message->endEdit.unchanged) {
|
||||
size_t newNameBytes;
|
||||
char *newName = EsTextboxGetContents(instance->fileMenuNameTextbox, &newNameBytes);
|
||||
uint8_t *buffer = (uint8_t *) EsHeapAllocate(1 + newNameBytes, false);
|
||||
|
|
|
@ -1691,7 +1691,7 @@ struct EsMessageGetBreadcrumb {
|
|||
};
|
||||
|
||||
struct EsMessageEndEdit {
|
||||
bool rejected;
|
||||
bool rejected, unchanged;
|
||||
};
|
||||
|
||||
// Instance messages.
|
||||
|
@ -1706,6 +1706,7 @@ struct EsMessageInstanceOpen {
|
|||
struct EsMessageInstanceSave {
|
||||
ES_INSTANCE_TYPE *instance;
|
||||
EsFileStore *file;
|
||||
STRING name;
|
||||
};
|
||||
|
||||
struct EsMessageInstanceDestroy {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#ifdef ENABLE_POSIX_SUBSYSTEM
|
||||
|
||||
#define ARRAY_DEFINITIONS_ONLY
|
||||
#include <shared/array.cpp>
|
||||
|
||||
extern "C" void *ProcessorTLSRead(uintptr_t offset);
|
||||
|
|
|
@ -3179,9 +3179,12 @@ void EsTextboxStartEdit(EsTextbox *textbox) {
|
|||
|
||||
void TextboxEndEdit(EsTextbox *textbox, bool reject) {
|
||||
if ((textbox->flags & ES_TEXTBOX_EDIT_BASED) && textbox->editing) {
|
||||
TextboxSetActiveLine(textbox, -1);
|
||||
textbox->editing = false;
|
||||
EsMessage m = { ES_MSG_TEXTBOX_EDIT_END };
|
||||
m.endEdit.rejected = reject;
|
||||
m.endEdit.unchanged = textbox->dataBytes == textbox->editStartContentBytes
|
||||
&& 0 == EsMemoryCompare(textbox->data, textbox->editStartContent, textbox->dataBytes);
|
||||
|
||||
if (reject || ES_REJECTED == EsMessageSend(textbox, &m)) {
|
||||
EsTextboxSelectAll(textbox);
|
||||
|
|
|
@ -125,6 +125,7 @@ KSpinlock ipiLock;
|
|||
#include <shared/heap.cpp>
|
||||
#include <shared/arena.cpp>
|
||||
#else
|
||||
#define ARRAY_IMPLEMENTATION_ONLY
|
||||
#include <shared/array.cpp>
|
||||
#include <shared/partitions.cpp>
|
||||
#endif
|
||||
|
|
|
@ -448,7 +448,9 @@ void *MMMapShared(MMSpace *space, MMSharedRegion *sharedRegion, uintptr_t offset
|
|||
// Panics on failure.
|
||||
void MMCheckUnusable(uintptr_t physicalStart, size_t bytes);
|
||||
|
||||
#define ARRAY_DEFINITIONS_ONLY
|
||||
#include <shared/array.cpp>
|
||||
#undef ARRAY_DEFINITIONS_ONLY
|
||||
|
||||
typedef SimpleList MMObjectCacheItem;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef IMPLEMENTATION
|
||||
#ifndef ARRAY_IMPLEMENTATION_ONLY
|
||||
|
||||
struct _ArrayHeader {
|
||||
size_t length, allocated;
|
||||
|
@ -71,7 +71,9 @@ struct Array {
|
|||
}
|
||||
};
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_DEFINITIONS_ONLY
|
||||
|
||||
bool _ArrayMaybeInitialise(void **array, size_t itemSize, EsHeap *heap) {
|
||||
if (*array) return true;
|
||||
|
|
1290
shared/stb_image.h
1290
shared/stb_image.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -189,6 +189,9 @@ DEFINE_INTERFACE_STRING(ImageEditorPickTool, "Pick tool");
|
|||
|
||||
DEFINE_INTERFACE_STRING(ImageEditorUnsupportedFormat, "The image is in an unsupported format. Try opening it with another application.");
|
||||
|
||||
DEFINE_INTERFACE_STRING(ImageEditorNewFileName, "untitled.png");
|
||||
DEFINE_INTERFACE_STRING(ImageEditorNewDocument, "New bitmap image");
|
||||
|
||||
DEFINE_INTERFACE_STRING(ImageEditorTitle, "Image Editor");
|
||||
|
||||
// Text Editor.
|
||||
|
|
|
@ -287,6 +287,7 @@ Option options[] = {
|
|||
{ "Flag._ALWAYS_USE_VBE", OPTION_TYPE_BOOL, { .b = false } },
|
||||
{ "Dependency.ACPICA", OPTION_TYPE_BOOL, { .b = true } },
|
||||
{ "Dependency.stb_image", OPTION_TYPE_BOOL, { .b = true } },
|
||||
{ "Dependency.stb_image_write", OPTION_TYPE_BOOL, { .b = true } },
|
||||
{ "Dependency.stb_sprintf", OPTION_TYPE_BOOL, { .b = true } },
|
||||
{ "Dependency.HarfBuzz", OPTION_TYPE_BOOL, { .b = true } },
|
||||
{ "Dependency.FreeType", OPTION_TYPE_BOOL, { .b = true } },
|
||||
|
|
|
@ -1266,6 +1266,8 @@ int main(int argc, char **argv) {
|
|||
strcat(kernelCompileFlags, " -DUSE_ACPICA ");
|
||||
} else if (0 == strcmp(s.key, "Dependency.stb_image") && atoi(s.value)) {
|
||||
strcat(commonCompileFlags, " -DUSE_STB_IMAGE ");
|
||||
} else if (0 == strcmp(s.key, "Dependency.stb_image_write") && atoi(s.value)) {
|
||||
strcat(commonCompileFlags, " -DUSE_STB_IMAGE_WRITE ");
|
||||
} else if (0 == strcmp(s.key, "Dependency.stb_sprintf") && atoi(s.value)) {
|
||||
strcat(commonCompileFlags, " -DUSE_STB_SPRINTF ");
|
||||
} else if (0 == strcmp(s.key, "Dependency.HarfBuzz") && atoi(s.value)) {
|
||||
|
|
Loading…
Reference in New Issue