diff --git a/apps/file_manager/main.cpp b/apps/file_manager/main.cpp index 516abd8..8fc2655 100644 --- a/apps/file_manager/main.cpp +++ b/apps/file_manager/main.cpp @@ -539,9 +539,10 @@ void _start() { // Enumerate drives. - EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) { - if (device.type == ES_DEVICE_FILE_SYSTEM) DriveAdd(device.handle, device.id); - }, 0); + size_t deviceCount; + EsMessageDevice *devices = EsDeviceEnumerate(&deviceCount); + for (uintptr_t i = 0; i < deviceCount; i++) if (devices[i].type == ES_DEVICE_FILE_SYSTEM) DriveAdd(devices[i].handle, devices[i].id); + EsHeapFree(devices); // Process messages. diff --git a/apps/file_manager/ui.cpp b/apps/file_manager/ui.cpp index 8218e4a..087b869 100644 --- a/apps/file_manager/ui.cpp +++ b/apps/file_manager/ui.cpp @@ -21,9 +21,10 @@ void InstanceFolderPathChanged(Instance *instance, bool fromLoadFolder) { EsWindowSetTitle(instance->window, (char *) buffer.out, buffer.position); EsWindowSetIcon(instance->window, knownFileTypes[instance->folder->containerHandler->getFileType(instance->path)].iconID); - EsListViewEnumerateVisibleItems(instance->list, [] (EsListView *, EsElement *item, uint32_t, EsListViewIndex index) { - ListItemCreated(item, index, true); - }); + size_t itemCount; + EsListViewEnumeratedVisibleItem *items = EsListViewEnumerateVisibleItems(instance->list, &itemCount); + for (uintptr_t i = 0; i < itemCount; i++) ListItemCreated(items[i].element, items[i].index, true); + EsHeapFree(items); } bool InstanceLoadFolder(Instance *instance, String path /* takes ownership */, int historyMode) { diff --git a/apps/font_book.cpp b/apps/font_book.cpp index db6e582..487223d 100644 --- a/apps/font_book.cpp +++ b/apps/font_book.cpp @@ -280,10 +280,10 @@ void VariantsPopupCreate(Instance *instance, EsElement *element, EsCommand *) { ES_MACRO_SORT(LoadFontsFromDatabaseSort, EsFontInformation, result = EsStringCompare(_left->name, _left->nameBytes, _right->name, _right->nameBytes);, int); void LoadFontsFromDatabase(Instance *instance) { - EsFontDatabaseEnumerate([] (const EsFontInformation *information, EsGeneric context) { - ((Instance *) context.p)->fonts.AddPointer(information); - }, instance); - + size_t fontCount; + EsFontInformation *fonts = EsFontDatabaseEnumerate(&fontCount); + for (uintptr_t i = 0; i < fontCount; i++) instance->fonts.Add(fonts[i]); + EsHeapFree(fonts); LoadFontsFromDatabaseSort(instance->fonts.array, instance->fonts.Length(), 0); EsListViewInsert(instance->fontList, 0, 0, instance->fonts.Length()); } diff --git a/apps/script_console.cpp b/apps/script_console.cpp index 47858c0..892a2d8 100644 --- a/apps/script_console.cpp +++ b/apps/script_console.cpp @@ -935,11 +935,16 @@ void _start() { // TODO Proper drive mounting. - EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) { - if (device.type == ES_DEVICE_FILE_SYSTEM && EsDeviceControl(device.handle, ES_DEVICE_CONTROL_FS_IS_BOOT, 0, nullptr)) { - EsMountPointAdd(EsLiteral("0:"), device.handle); + size_t deviceCount; + EsMessageDevice *devices = EsDeviceEnumerate(&deviceCount); + + for (uintptr_t i = 0; i < deviceCount; i++) { + if (devices[i].type == ES_DEVICE_FILE_SYSTEM && EsDeviceControl(devices[i].handle, ES_DEVICE_CONTROL_FS_IS_BOOT, 0, nullptr)) { + EsMountPointAdd(EsLiteral("0:"), devices[i].handle); } - }, 0); + } + + EsHeapFree(devices); while (true) { EsMessage *message = EsMessageReceive(); diff --git a/desktop/api.cpp b/desktop/api.cpp index dd14e71..b751a70 100644 --- a/desktop/api.cpp +++ b/desktop/api.cpp @@ -274,12 +274,14 @@ uintptr_t APISyscallCheckForCrash(uintptr_t argument0, uintptr_t argument1, uint } #endif -void EsDeviceEnumerate(EsDeviceEnumerationCallback callback, EsGeneric context) { +EsMessageDevice *EsDeviceEnumerate(size_t *count) { EsMessageMutexCheck(); - - for (uintptr_t i = 0; i < api.connectedDevices.Length(); i++) { - callback(api.connectedDevices[i], context); - } + *count = 0; + EsMessageDevice *result = (EsMessageDevice *) EsHeapAllocate(sizeof(EsMessageDevice) * api.connectedDevices.Length(), true); + if (!result) return nullptr; + *count = api.connectedDevices.Length(); + for (uintptr_t i = 0; i < api.connectedDevices.Length(); i++) result[i] = api.connectedDevices[i]; + return result; } EsSystemConfigurationItem *SystemConfigurationGetItem(EsSystemConfigurationGroup *group, const char *key, ptrdiff_t keyBytes, bool createIfNeeded) { diff --git a/desktop/list_view.cpp b/desktop/list_view.cpp index 4db86f3..a4baada 100644 --- a/desktop/list_view.cpp +++ b/desktop/list_view.cpp @@ -3033,10 +3033,23 @@ void EsListViewScrollToEnd(EsListView *view) { } } -void EsListViewEnumerateVisibleItems(EsListView *view, EsListViewEnumerateVisibleItemsCallback callback) { - for (uintptr_t i = 0; i < view->visibleItems.Length(); i++) { - callback(view, view->visibleItems[i].element, view->visibleItems[i].group, view->visibleItems[i].index); +EsListViewEnumeratedVisibleItem *EsListViewEnumerateVisibleItems(EsListView *view, size_t *count) { + EsMessageMutexCheck(); + *count = view->visibleItems.Length(); + EsListViewEnumeratedVisibleItem *result = (EsListViewEnumeratedVisibleItem *) EsHeapAllocate(sizeof(EsListViewEnumeratedVisibleItem) * *count, true); + + if (!result) { + *count = 0; + return nullptr; } + + for (uintptr_t i = 0; i < *count; i++) { + result[i].element = view->visibleItems[i].element; + result[i].group = view->visibleItems[i].group; + result[i].index = view->visibleItems[i].index; + } + + return result; } void EsListViewSetMaximumItemsPerBand(EsListView *view, int maximumItemsPerBand) { diff --git a/desktop/os.header b/desktop/os.header index 6cd17f2..a6622f4 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -1975,6 +1975,11 @@ struct EsCornerRadii { uint32_t tl, tr, bl, br; }; +struct EsListViewEnumeratedVisibleItem { + EsElement *element; + EsListViewIndex group, index; +}; + // Function pointer types. function_pointer void EsThreadEntryCallback(EsGeneric argument); @@ -1983,8 +1988,6 @@ function_pointer int EsCRTComparisonCallback(const void *left, const void *right function_pointer void EsTimerCallback(EsGeneric argument); function_pointer void EsMenuCallback(EsMenu *menu, EsGeneric context); function_pointer void EsUndoCallback(const void *item, EsUndoManager *manager, EsMessage *message); -function_pointer void EsDeviceEnumerationCallback(EsMessageDevice device, EsGeneric context); -function_pointer void EsListViewEnumerateVisibleItemsCallback(EsListView *view, EsElement *item, uint32_t group, EsListViewIndex index); function_pointer void EsFontEnumerationCallback(const EsFontInformation *information, EsGeneric context); function_pointer void EsUserTaskCallback(EsUserTask *task, EsGeneric data); function_pointer bool EsFileCopyCallback(EsFileOffset bytesCopied, EsFileOffset totalBytes, EsGeneric data); // Return false to cancel. @@ -2067,7 +2070,7 @@ function void EsOpenDocumentQueryInformation(STRING filePath, EsOpenDocumentInfo function void _EsPathAnnouncePathMoved(STRING oldPath, STRING newPath); // Set oldPathBytes = 0 to make the file manager refresh the path. function void _EsOpenDocumentEnumerate(EsBuffer *outputBuffer) @opaque(outputBuffer); -function void EsDeviceEnumerate(EsDeviceEnumerationCallback callback, EsGeneric context) @todo(); +function EsMessageDevice *EsDeviceEnumerate(size_t *count) @out(count) @heap_array_out(return, count*); // This must be done with the message mutex acquired. As soon as EsMessageReceived is next called, or the message mutex is released, then the handles in this array are invalid. function EsError EsDeviceControl(EsHandle handle, EsDeviceControlType type, void *dp, void *dq) @native(); // Processes and threads. @@ -2093,7 +2096,7 @@ function bool EsWorkIsExiting(); function const void *EsBufferRead(EsBuffer *buffer, size_t readBytes) @native(); function bool EsBufferReadInto(EsBuffer *buffer, void *destination, size_t readBytes) @buffer_out(destination, readBytes) @opaque(buffer); -function const void *EsBufferReadMany(struct EsBuffer *buffer, size_t a, size_t b) @native(); +function const void *EsBufferReadMany(EsBuffer *buffer, size_t a, size_t b) @native(); function int32_t EsBufferReadInt32Endian(EsBuffer *buffer, int32_t errorValue) @opaque(buffer); function void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writeBytes) @buffer_in(source, writeBytes) @opaque(buffer) @todo(); function bool EsBufferWriteInt8(EsBuffer *buffer, int8_t value) @opaque(buffer); @@ -2212,7 +2215,7 @@ function void EsTextPlanReplaceStyleRenderProperties(EsTextPlan *plan, const EsT function void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes, char **outString, EsTextRun **outTextRuns, size_t *outTextRunCount, EsTextStyle *baseStyle) @todo(); -function void EsFontDatabaseEnumerate(EsFontEnumerationCallback callback, EsGeneric context) @todo(); +function EsFontInformation *EsFontDatabaseEnumerate(size_t *count) @out(count) @heap_array_out(return, count*); function bool EsFontDatabaseLookupByName(STRING name, EsFontInformation *information) @out(information); // Returns false if the font does not exist in the database. function bool EsFontDatabaseLookupByID(EsFontFamily id, EsFontInformation *information) @out(information); // Returns false if the font does not exist in the database. function EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFileStore *store) @in(information); // Don't set the `id` field in EsFontInformation. The assigned ID will be returned. If nameBytes is 0, then the system will not try to match it with an existing font family. Set the corresponding bit in availableWeightsNormal/availableWeightsItalic for the file being added. The request is ignored if the specific variant is already in the database. @@ -2593,7 +2596,7 @@ function EsListView *EsListViewCreate(EsElement *parent, uint64_t flags = ES_FLA const EsStyle *headerItemStyle = ES_NULL, const EsStyle *footerItemStyle = ES_NULL); function EsListViewIndex EsListViewGetIndexFromItem(EsElement *element, EsListViewIndex *group = ES_NULL) @out(group); -function void EsListViewEnumerateVisibleItems(EsListView *view, EsListViewEnumerateVisibleItemsCallback callback) @todo(); +function EsListViewEnumeratedVisibleItem *EsListViewEnumerateVisibleItems(EsListView *view, size_t *count) @out(count) @heap_array_out(return, count*); function void EsListViewRegisterColumn(EsListView *view, uint32_t id, STRING title = BLANK_STRING, uint32_t flags = ES_FLAGS_DEFAULT, double initialWidth = 0); function void EsListViewAddAllColumns(EsListView *view); // Call after registering the columns to add them to the header. Call again after EsListViewChangeStyles, as needed. diff --git a/desktop/text.cpp b/desktop/text.cpp index b172169..f0500f1 100644 --- a/desktop/text.cpp +++ b/desktop/text.cpp @@ -748,14 +748,15 @@ EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFi return 0; } -void EsFontDatabaseEnumerate(EsFontEnumerationCallback callback, EsGeneric context) { +EsFontInformation *EsFontDatabaseEnumerate(size_t *count) { + // TODO Locking. FontInitialise(); - - for (uintptr_t i = 1; i < fontManagement.database.Length(); i++) { - EsFontInformation information; - EsFontDatabaseLookupByID(i, &information); - callback(&information, context); - } + *count = 0; + EsFontInformation *result = (EsFontInformation *) EsHeapAllocate(sizeof(EsFontInformation) * (fontManagement.database.Length() - 1), true); + if (!result) return nullptr; + *count = fontManagement.database.Length() - 1; + for (uintptr_t i = 1; i <= *count; i++) EsFontDatabaseLookupByID(i, &result[i - 1]); + return result; } bool FontSupportsScript(FontDatabaseEntry *entry, uint32_t _script, bool first) {