add first working cocoa code newapi

Wed, 04 Dec 2024 08:55:49 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 04 Dec 2024 08:55:49 +0100
branch
newapi
changeset 404
384f6d1f5784
parent 403
b59935b2de79
child 405
a7f18dda6baf

add first working cocoa code

.hgignore file | annotate | diff | comparison | revisions
application/Makefile file | annotate | diff | comparison | revisions
application/main.c file | annotate | diff | comparison | revisions
configure file | annotate | diff | comparison | revisions
make/project.xml file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit.xcodeproj/project.xcworkspace/contents.xcworkspacedata file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit.xcodeproj/xcshareddata/xcschemes/toolkit.xcscheme file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/Assets.xcassets/AccentColor.colorset/Contents.json file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/Assets.xcassets/AppIcon.appiconset/Contents.json file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/Assets.xcassets/Contents.json file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/Base.lproj/MainMenu.xib file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/main.m file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/toolkit.entitlements file | annotate | diff | comparison | revisions
resource/template.app/Contents/Info.plist file | annotate | diff | comparison | revisions
resource/template.app/Contents/Resources/Base.lproj/MainMenu.nib file | annotate | diff | comparison | revisions
resource/template.app/Contents/Resources/English.lproj/InfoPlist.strings file | annotate | diff | comparison | revisions
resource/template.app/Contents/Resources/English.lproj/MainMenu.nib file | annotate | diff | comparison | revisions
ui/cocoa/EventData.h file | annotate | diff | comparison | revisions
ui/cocoa/EventData.m file | annotate | diff | comparison | revisions
ui/cocoa/GridLayout.h file | annotate | diff | comparison | revisions
ui/cocoa/GridLayout.m file | annotate | diff | comparison | revisions
ui/cocoa/MainWindow.h file | annotate | diff | comparison | revisions
ui/cocoa/MainWindow.m file | annotate | diff | comparison | revisions
ui/cocoa/Makefile file | annotate | diff | comparison | revisions
ui/cocoa/UiJob.h file | annotate | diff | comparison | revisions
ui/cocoa/UiJob.m file | annotate | diff | comparison | revisions
ui/cocoa/WindowManager.h file | annotate | diff | comparison | revisions
ui/cocoa/WindowManager.m file | annotate | diff | comparison | revisions
ui/cocoa/appdelegate.h file | annotate | diff | comparison | revisions
ui/cocoa/appdelegate.m file | annotate | diff | comparison | revisions
ui/cocoa/button.h file | annotate | diff | comparison | revisions
ui/cocoa/button.m file | annotate | diff | comparison | revisions
ui/cocoa/container.h file | annotate | diff | comparison | revisions
ui/cocoa/container.m file | annotate | diff | comparison | revisions
ui/cocoa/graphics.h file | annotate | diff | comparison | revisions
ui/cocoa/graphics.m file | annotate | diff | comparison | revisions
ui/cocoa/menu.h file | annotate | diff | comparison | revisions
ui/cocoa/menu.m file | annotate | diff | comparison | revisions
ui/cocoa/objs.mk file | annotate | diff | comparison | revisions
ui/cocoa/resource.h file | annotate | diff | comparison | revisions
ui/cocoa/resource.m file | annotate | diff | comparison | revisions
ui/cocoa/stock.h file | annotate | diff | comparison | revisions
ui/cocoa/stock.m file | annotate | diff | comparison | revisions
ui/cocoa/text.h file | annotate | diff | comparison | revisions
ui/cocoa/text.m file | annotate | diff | comparison | revisions
ui/cocoa/toolbar.h file | annotate | diff | comparison | revisions
ui/cocoa/toolbar.m file | annotate | diff | comparison | revisions
ui/cocoa/toolkit.h file | annotate | diff | comparison | revisions
ui/cocoa/toolkit.m file | annotate | diff | comparison | revisions
ui/cocoa/tree.h file | annotate | diff | comparison | revisions
ui/cocoa/tree.m file | annotate | diff | comparison | revisions
ui/cocoa/window.h file | annotate | diff | comparison | revisions
ui/cocoa/window.m file | annotate | diff | comparison | revisions
ui/common/menu.c file | annotate | diff | comparison | revisions
ui/common/object.c file | annotate | diff | comparison | revisions
ui/common/object.h file | annotate | diff | comparison | revisions
ui/common/threadpool.c file | annotate | diff | comparison | revisions
ui/common/threadpool.h file | annotate | diff | comparison | revisions
ui/ui/container.h file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/.hgignore	Sat Nov 30 20:33:16 2024 +0100
+++ b/.hgignore	Wed Dec 04 08:55:49 2024 +0100
@@ -4,12 +4,5 @@
 relre:^make/vs/.vs/.*
 relre:^make/vs/packages/.*
 relre:^make/vs/.*vcxproj\.user
-relre:^ui/winui/winui\.vcxproj\.user
-relre:^ui/winui/Generated Files
-relre:^ui/wpf/UIcore/obj
-relre:^ui/wpf/UIwrapper/.vs
-relre:^ui/wpf/UIwrapper/UIwrapper.VC
-relre:^ui/wpf/UIwrapper/UIwrapper/Debug
-relre:^ui/wpf/UIwrapper/UIwrapper/Release
-relre:^ui/wpf/UIwrapper/UIwrapper/x64
-relre:^ui/wpf/UIwrapper/ipch
\ No newline at end of file
+relre:^make/xcode/toolkit/toolkit.xcodeproj/xcuserdata/.*
+relre:^make/xcode/toolkit/toolkit.xcodeproj/project.xcworkspace/xcuserdata/.*
\ No newline at end of file
--- a/application/Makefile	Sat Nov 30 20:33:16 2024 +0100
+++ b/application/Makefile	Wed Dec 04 08:55:49 2024 +0100
@@ -33,13 +33,13 @@
 
 SRC = main.c
 
-OBJ = $(SRC:%.c=../build/application/%.$(OBJ_EXT))
+OBJ = $(SRC:%.c=../build/application/%$(OBJ_EXT))
 
 all: ../build/bin/mk12
 
 ../build/bin/mk12: $(OBJ) $(BUILD_ROOT)/build/lib/libuitk.a
 	$(CC) -o ../build/bin/mk12$(APP_EXT) $(OBJ) -L$(BUILD_ROOT)/build/lib -luitk -lucx $(LDFLAGS) $(TK_LDFLAGS)
 
-../build/application/%.$(OBJ_EXT): %.c
-	$(CC) ../ucx $(CFLAGS) $(TK_CFLAGS) -o $@ -c $<
+../build/application/%$(OBJ_EXT): %.c
+	$(CC) $(CFLAGS) $(TK_CFLAGS) -o $@ -c $<
 
--- a/application/main.c	Sat Nov 30 20:33:16 2024 +0100
+++ b/application/main.c	Wed Dec 04 08:55:49 2024 +0100
@@ -28,11 +28,14 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <ui/ui.h>
 #include <cx/buffer.h>
 #include <cx/utils.h>
 
+#ifndef UI_COCOA
+
 typedef struct {
     UiString *str1;
     UiString *str2;
@@ -449,3 +452,20 @@
     
     return (EXIT_SUCCESS);
 }
+
+#endif
+
+#ifdef UI_COCOA
+
+void application_startup(UiEvent *event, void *data) {
+
+}
+
+int main(int argc, char** argv) {
+    ui_init("app1", argc, argv);
+    ui_onstartup(application_startup, NULL);
+    ui_main();
+    return (EXIT_SUCCESS);
+}
+
+#endif
--- a/configure	Sat Nov 30 20:33:16 2024 +0100
+++ b/configure	Wed Dec 04 08:55:49 2024 +0100
@@ -72,7 +72,7 @@
 Options:
   --debug                 add extra compile flags for debug builds
   --release               add extra compile flags for release builds
-  --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|motif)
+  --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|cocoa|motif)
 
 __EOF__
 }
@@ -672,6 +672,20 @@
 __EOF__
     return 0
 }
+checkopt_toolkit_cocoa()
+{
+    VERR=0
+    if dependency_error_cocoa ; then
+        VERR=1
+    fi
+    if [ $VERR -ne 0 ]; then
+        return 1
+    fi
+    cat >> "$TEMP_DIR/make.mk" << __EOF__
+TOOLKIT = cocoa
+__EOF__
+    return 0
+}
 checkopt_toolkit_motif()
 {
     VERR=0
@@ -816,6 +830,14 @@
             ERROR=1
             DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED"
         fi
+    elif [ "$OPT_TOOLKIT" = "cocoa" ]; then
+        echo "  toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options
+        if checkopt_toolkit_cocoa ; then
+            :
+        else
+            ERROR=1
+            DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED"
+        fi
     elif [ "$OPT_TOOLKIT" = "motif" ]; then
         echo "  toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options
         if checkopt_toolkit_motif ; then
--- a/make/project.xml	Sat Nov 30 20:33:16 2024 +0100
+++ b/make/project.xml	Wed Dec 04 08:55:49 2024 +0100
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://unixwork.de/uwproj">
+<project version="0.3" xmlns="http://unixwork.de/uwproj">
 	<dependency>
 		<lang>c</lang>
 	</dependency>
@@ -36,15 +36,15 @@
 	<!--
 	<dependency name="qt4">
 		<test>which qmake-qt4</test>
-		<cflags type="exec">qmake-qt4 -o - /dev/null | grep DEFINES\ </cflags>
-		<cflags type="exec">qmake-qt4 -o - /dev/null | grep INCPATH\ </cflags>
-		<ldflags type="exec"><cflags type="exec">qmake-qt4 -o - /dev/null | grep LIBS\ </cflags></ldflags>
+		<cflags exec="true">qmake-qt4 -o - /dev/null | grep DEFINES\ </cflags>
+		<cflags exec="true">qmake-qt4 -o - /dev/null | grep INCPATH\ </cflags>
+		<ldflags exec="true">qmake-qt4 -o - /dev/null | grep LIBS\ </ldflags>
 	</dependency>
 	<dependency name="qt5">
 		<test>which qmake-qt5</test>
-		<cflags type="exec">qmake-qt5 -o - /dev/null | grep DEFINES\ </cflags>
-		<cflags type="exec">qmake-qt5 -o - /dev/null | grep INCPATH\ </cflags>
-		<ldflags type="exec"><cflags type="exec">qmake-qt5 -o - /dev/null | grep LIBS\ </cflags></ldflags>
+		<cflags exec="true">qmake-qt5 -o - /dev/null | grep DEFINES\ </cflags>
+		<cflags exec="true">qmake-qt5 -o - /dev/null | grep INCPATH\ </cflags>
+		<ldflags exec="true">qmake-qt5 -o - /dev/null | grep LIBS\ </ldflags>
 	</dependency>
 	-->
 	<dependency name="cocoa" platform="macos">
@@ -115,6 +115,10 @@
 				<make>TOOLKIT = qt</make>
 				<make>LD = $(CXX)</make>
 			</value>
+			<value str="cocoa">
+				<dependencies>cocoa</dependencies>
+				<make>TOOLKIT = cocoa</make>
+			</value>
 			<value str="motif">
 				<dependencies>motif</dependencies>
 				<make>TOOLKIT = motif</make>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,630 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 77;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		ED6580EE2CFF19F900F5402F /* context.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580DD2CFF19F900F5402F /* context.c */; };
+		ED6580EF2CFF19F900F5402F /* menu.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580E12CFF19F900F5402F /* menu.c */; };
+		ED6580F02CFF19F900F5402F /* threadpool.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580E72CFF19F900F5402F /* threadpool.c */; };
+		ED6580F12CFF19F900F5402F /* condvar.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580DB2CFF19F900F5402F /* condvar.c */; };
+		ED6580F22CFF19F900F5402F /* document.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580DF2CFF19F900F5402F /* document.c */; };
+		ED6580F32CFF19F900F5402F /* object.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580E32CFF19F900F5402F /* object.c */; };
+		ED6580F42CFF19F900F5402F /* toolbar.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580E92CFF19F900F5402F /* toolbar.c */; };
+		ED6580F52CFF19F900F5402F /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580EB2CFF19F900F5402F /* types.c */; };
+		ED6580F62CFF19F900F5402F /* properties.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580E52CFF19F900F5402F /* properties.c */; };
+		ED6580F72CFF19F900F5402F /* ucx_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580ED2CFF19F900F5402F /* ucx_properties.c */; };
+		ED65811D2CFF1A3000F5402F /* linked_list.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581142CFF1A3000F5402F /* linked_list.c */; };
+		ED65811E2CFF1A3000F5402F /* tree.c in Sources */ = {isa = PBXBuildFile; fileRef = ED65811B2CFF1A3000F5402F /* tree.c */; };
+		ED6581202CFF1A3000F5402F /* mempool.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581172CFF1A3000F5402F /* mempool.c */; };
+		ED6581212CFF1A3000F5402F /* map.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581162CFF1A3000F5402F /* map.c */; };
+		ED6581222CFF1A3000F5402F /* hash_map.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581122CFF1A3000F5402F /* hash_map.c */; };
+		ED6581232CFF1A3000F5402F /* array_list.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580FA2CFF1A3000F5402F /* array_list.c */; };
+		ED6581242CFF1A3000F5402F /* list.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581152CFF1A3000F5402F /* list.c */; };
+		ED6581252CFF1A3000F5402F /* compare.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580FC2CFF1A3000F5402F /* compare.c */; };
+		ED6581262CFF1A3000F5402F /* hash_key.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581112CFF1A3000F5402F /* hash_key.c */; };
+		ED6581272CFF1A3000F5402F /* iterator.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581132CFF1A3000F5402F /* iterator.c */; };
+		ED6581282CFF1A3000F5402F /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581192CFF1A3000F5402F /* string.c */; };
+		ED6581292CFF1A3000F5402F /* allocator.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580F92CFF1A3000F5402F /* allocator.c */; };
+		ED65812A2CFF1A3000F5402F /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = ED65811C2CFF1A3000F5402F /* utils.c */; };
+		ED65812B2CFF1A3000F5402F /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6580FB2CFF1A3000F5402F /* buffer.c */; };
+		ED65812C2CFF1A3000F5402F /* printf.c in Sources */ = {isa = PBXBuildFile; fileRef = ED6581182CFF1A3000F5402F /* printf.c */; };
+		ED65812D2CFF1A3000F5402F /* common.h.orig in Resources */ = {isa = PBXBuildFile; fileRef = ED6581022CFF1A3000F5402F /* common.h.orig */; };
+		ED6581312CFF1A8800F5402F /* toolkit.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6581302CFF1A8800F5402F /* toolkit.m */; };
+		ED6581342CFF1F1900F5402F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6581332CFF1F1900F5402F /* AppDelegate.m */; };
+		ED6581392CFF287300F5402F /* EventData.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6581362CFF287300F5402F /* EventData.m */; };
+		ED65813A2CFF287300F5402F /* UiJob.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6581382CFF287300F5402F /* UiJob.m */; };
+		ED6581432CFF3BCE00F5402F /* window.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6581422CFF3BCE00F5402F /* window.m */; };
+		ED6581442CFF3BCE00F5402F /* button.m in Sources */ = {isa = PBXBuildFile; fileRef = ED65813C2CFF3BCE00F5402F /* button.m */; };
+		ED6581452CFF3BCE00F5402F /* Container.m in Sources */ = {isa = PBXBuildFile; fileRef = ED65813E2CFF3BCE00F5402F /* Container.m */; };
+		ED6581462CFF3BCE00F5402F /* GridLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6581402CFF3BCE00F5402F /* GridLayout.m */; };
+		ED65815C2CFF3EE900F5402F /* MainWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = ED65815B2CFF3EE900F5402F /* MainWindow.m */; };
+		ED65815F2CFF4BF200F5402F /* WindowManager.m in Sources */ = {isa = PBXBuildFile; fileRef = ED65815E2CFF4BF200F5402F /* WindowManager.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		ED6580AC2CFF122700F5402F /* toolkit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = toolkit.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		ED6580DA2CFF19F900F5402F /* condvar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = condvar.h; path = /Users/olaf/Projekte/toolkit/ui/common/condvar.h; sourceTree = "<absolute>"; };
+		ED6580DB2CFF19F900F5402F /* condvar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = condvar.c; path = /Users/olaf/Projekte/toolkit/ui/common/condvar.c; sourceTree = "<absolute>"; };
+		ED6580DC2CFF19F900F5402F /* context.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = context.h; path = /Users/olaf/Projekte/toolkit/ui/common/context.h; sourceTree = "<absolute>"; };
+		ED6580DD2CFF19F900F5402F /* context.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = context.c; path = /Users/olaf/Projekte/toolkit/ui/common/context.c; sourceTree = "<absolute>"; };
+		ED6580DE2CFF19F900F5402F /* document.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = document.h; path = /Users/olaf/Projekte/toolkit/ui/common/document.h; sourceTree = "<absolute>"; };
+		ED6580DF2CFF19F900F5402F /* document.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = document.c; path = /Users/olaf/Projekte/toolkit/ui/common/document.c; sourceTree = "<absolute>"; };
+		ED6580E02CFF19F900F5402F /* menu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = menu.h; path = /Users/olaf/Projekte/toolkit/ui/common/menu.h; sourceTree = "<absolute>"; };
+		ED6580E12CFF19F900F5402F /* menu.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = menu.c; path = /Users/olaf/Projekte/toolkit/ui/common/menu.c; sourceTree = "<absolute>"; };
+		ED6580E22CFF19F900F5402F /* object.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = object.h; path = /Users/olaf/Projekte/toolkit/ui/common/object.h; sourceTree = "<absolute>"; };
+		ED6580E32CFF19F900F5402F /* object.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = object.c; path = /Users/olaf/Projekte/toolkit/ui/common/object.c; sourceTree = "<absolute>"; };
+		ED6580E42CFF19F900F5402F /* properties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = properties.h; path = /Users/olaf/Projekte/toolkit/ui/common/properties.h; sourceTree = "<absolute>"; };
+		ED6580E52CFF19F900F5402F /* properties.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = properties.c; path = /Users/olaf/Projekte/toolkit/ui/common/properties.c; sourceTree = "<absolute>"; };
+		ED6580E62CFF19F900F5402F /* threadpool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = threadpool.h; path = /Users/olaf/Projekte/toolkit/ui/common/threadpool.h; sourceTree = "<absolute>"; };
+		ED6580E72CFF19F900F5402F /* threadpool.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = threadpool.c; path = /Users/olaf/Projekte/toolkit/ui/common/threadpool.c; sourceTree = "<absolute>"; };
+		ED6580E82CFF19F900F5402F /* toolbar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = toolbar.h; path = /Users/olaf/Projekte/toolkit/ui/common/toolbar.h; sourceTree = "<absolute>"; };
+		ED6580E92CFF19F900F5402F /* toolbar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = toolbar.c; path = /Users/olaf/Projekte/toolkit/ui/common/toolbar.c; sourceTree = "<absolute>"; };
+		ED6580EA2CFF19F900F5402F /* types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = types.h; path = /Users/olaf/Projekte/toolkit/ui/common/types.h; sourceTree = "<absolute>"; };
+		ED6580EB2CFF19F900F5402F /* types.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = types.c; path = /Users/olaf/Projekte/toolkit/ui/common/types.c; sourceTree = "<absolute>"; };
+		ED6580EC2CFF19F900F5402F /* ucx_properties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ucx_properties.h; path = /Users/olaf/Projekte/toolkit/ui/common/ucx_properties.h; sourceTree = "<absolute>"; };
+		ED6580ED2CFF19F900F5402F /* ucx_properties.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = ucx_properties.c; path = /Users/olaf/Projekte/toolkit/ui/common/ucx_properties.c; sourceTree = "<absolute>"; };
+		ED6580F92CFF1A3000F5402F /* allocator.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = allocator.c; path = /Users/olaf/Projekte/toolkit/ucx/allocator.c; sourceTree = "<absolute>"; };
+		ED6580FA2CFF1A3000F5402F /* array_list.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = array_list.c; path = /Users/olaf/Projekte/toolkit/ucx/array_list.c; sourceTree = "<absolute>"; };
+		ED6580FB2CFF1A3000F5402F /* buffer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = buffer.c; path = /Users/olaf/Projekte/toolkit/ucx/buffer.c; sourceTree = "<absolute>"; };
+		ED6580FC2CFF1A3000F5402F /* compare.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = compare.c; path = /Users/olaf/Projekte/toolkit/ucx/compare.c; sourceTree = "<absolute>"; };
+		ED6580FD2CFF1A3000F5402F /* allocator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = allocator.h; sourceTree = "<group>"; };
+		ED6580FE2CFF1A3000F5402F /* array_list.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = array_list.h; sourceTree = "<group>"; };
+		ED6580FF2CFF1A3000F5402F /* buffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = buffer.h; sourceTree = "<group>"; };
+		ED6581002CFF1A3000F5402F /* collection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = collection.h; sourceTree = "<group>"; };
+		ED6581012CFF1A3000F5402F /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
+		ED6581022CFF1A3000F5402F /* common.h.orig */ = {isa = PBXFileReference; lastKnownFileType = text; path = common.h.orig; sourceTree = "<group>"; };
+		ED6581032CFF1A3000F5402F /* compare.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = compare.h; sourceTree = "<group>"; };
+		ED6581042CFF1A3000F5402F /* hash_key.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hash_key.h; sourceTree = "<group>"; };
+		ED6581052CFF1A3000F5402F /* hash_map.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = hash_map.h; sourceTree = "<group>"; };
+		ED6581062CFF1A3000F5402F /* iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iterator.h; sourceTree = "<group>"; };
+		ED6581072CFF1A3000F5402F /* linked_list.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = linked_list.h; sourceTree = "<group>"; };
+		ED6581082CFF1A3000F5402F /* list.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = "<group>"; };
+		ED6581092CFF1A3000F5402F /* map.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = map.h; sourceTree = "<group>"; };
+		ED65810A2CFF1A3000F5402F /* mempool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mempool.h; sourceTree = "<group>"; };
+		ED65810B2CFF1A3000F5402F /* printf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = printf.h; sourceTree = "<group>"; };
+		ED65810C2CFF1A3000F5402F /* string.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = string.h; sourceTree = "<group>"; };
+		ED65810D2CFF1A3000F5402F /* test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = test.h; sourceTree = "<group>"; };
+		ED65810E2CFF1A3000F5402F /* tree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tree.h; sourceTree = "<group>"; };
+		ED65810F2CFF1A3000F5402F /* utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
+		ED6581112CFF1A3000F5402F /* hash_key.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = hash_key.c; path = /Users/olaf/Projekte/toolkit/ucx/hash_key.c; sourceTree = "<absolute>"; };
+		ED6581122CFF1A3000F5402F /* hash_map.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = hash_map.c; path = /Users/olaf/Projekte/toolkit/ucx/hash_map.c; sourceTree = "<absolute>"; };
+		ED6581132CFF1A3000F5402F /* iterator.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = iterator.c; path = /Users/olaf/Projekte/toolkit/ucx/iterator.c; sourceTree = "<absolute>"; };
+		ED6581142CFF1A3000F5402F /* linked_list.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = linked_list.c; path = /Users/olaf/Projekte/toolkit/ucx/linked_list.c; sourceTree = "<absolute>"; };
+		ED6581152CFF1A3000F5402F /* list.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = list.c; path = /Users/olaf/Projekte/toolkit/ucx/list.c; sourceTree = "<absolute>"; };
+		ED6581162CFF1A3000F5402F /* map.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = map.c; path = /Users/olaf/Projekte/toolkit/ucx/map.c; sourceTree = "<absolute>"; };
+		ED6581172CFF1A3000F5402F /* mempool.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = mempool.c; path = /Users/olaf/Projekte/toolkit/ucx/mempool.c; sourceTree = "<absolute>"; };
+		ED6581182CFF1A3000F5402F /* printf.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = printf.c; path = /Users/olaf/Projekte/toolkit/ucx/printf.c; sourceTree = "<absolute>"; };
+		ED6581192CFF1A3000F5402F /* string.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = string.c; path = /Users/olaf/Projekte/toolkit/ucx/string.c; sourceTree = "<absolute>"; };
+		ED65811B2CFF1A3000F5402F /* tree.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = tree.c; path = /Users/olaf/Projekte/toolkit/ucx/tree.c; sourceTree = "<absolute>"; };
+		ED65811C2CFF1A3000F5402F /* utils.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = utils.c; path = /Users/olaf/Projekte/toolkit/ucx/utils.c; sourceTree = "<absolute>"; };
+		ED65812F2CFF1A8800F5402F /* toolkit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = toolkit.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/toolkit.h; sourceTree = "<absolute>"; };
+		ED6581302CFF1A8800F5402F /* toolkit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = toolkit.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/toolkit.m; sourceTree = "<absolute>"; };
+		ED6581322CFF1F1900F5402F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/AppDelegate.h; sourceTree = "<absolute>"; };
+		ED6581332CFF1F1900F5402F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/AppDelegate.m; sourceTree = "<absolute>"; };
+		ED6581352CFF287300F5402F /* EventData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EventData.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/EventData.h; sourceTree = "<absolute>"; };
+		ED6581362CFF287300F5402F /* EventData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = EventData.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/EventData.m; sourceTree = "<absolute>"; };
+		ED6581372CFF287300F5402F /* UiJob.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UiJob.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/UiJob.h; sourceTree = "<absolute>"; };
+		ED6581382CFF287300F5402F /* UiJob.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = UiJob.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/UiJob.m; sourceTree = "<absolute>"; };
+		ED65813B2CFF3BCE00F5402F /* button.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = button.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/button.h; sourceTree = "<absolute>"; };
+		ED65813C2CFF3BCE00F5402F /* button.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = button.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/button.m; sourceTree = "<absolute>"; };
+		ED65813D2CFF3BCE00F5402F /* Container.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Container.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/Container.h; sourceTree = "<absolute>"; };
+		ED65813E2CFF3BCE00F5402F /* Container.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Container.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/Container.m; sourceTree = "<absolute>"; };
+		ED65813F2CFF3BCE00F5402F /* GridLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GridLayout.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/GridLayout.h; sourceTree = "<absolute>"; };
+		ED6581402CFF3BCE00F5402F /* GridLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = GridLayout.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/GridLayout.m; sourceTree = "<absolute>"; };
+		ED6581412CFF3BCE00F5402F /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = window.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/window.h; sourceTree = "<absolute>"; };
+		ED6581422CFF3BCE00F5402F /* window.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = window.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/window.m; sourceTree = "<absolute>"; };
+		ED6581482CFF3CA000F5402F /* button.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = button.h; path = /Users/olaf/Projekte/toolkit/ui/ui/button.h; sourceTree = "<absolute>"; };
+		ED6581492CFF3CA000F5402F /* container.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = container.h; path = /Users/olaf/Projekte/toolkit/ui/ui/container.h; sourceTree = "<absolute>"; };
+		ED65814A2CFF3CA000F5402F /* display.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = display.h; path = /Users/olaf/Projekte/toolkit/ui/ui/display.h; sourceTree = "<absolute>"; };
+		ED65814B2CFF3CA000F5402F /* dnd.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dnd.h; path = /Users/olaf/Projekte/toolkit/ui/ui/dnd.h; sourceTree = "<absolute>"; };
+		ED65814C2CFF3CA000F5402F /* entry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = entry.h; path = /Users/olaf/Projekte/toolkit/ui/ui/entry.h; sourceTree = "<absolute>"; };
+		ED65814D2CFF3CA000F5402F /* graphics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = graphics.h; path = /Users/olaf/Projekte/toolkit/ui/ui/graphics.h; sourceTree = "<absolute>"; };
+		ED65814E2CFF3CA000F5402F /* icons.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = icons.h; path = /Users/olaf/Projekte/toolkit/ui/ui/icons.h; sourceTree = "<absolute>"; };
+		ED65814F2CFF3CA000F5402F /* image.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = image.h; path = /Users/olaf/Projekte/toolkit/ui/ui/image.h; sourceTree = "<absolute>"; };
+		ED6581502CFF3CA000F5402F /* menu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = menu.h; path = /Users/olaf/Projekte/toolkit/ui/ui/menu.h; sourceTree = "<absolute>"; };
+		ED6581512CFF3CA000F5402F /* properties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = properties.h; path = /Users/olaf/Projekte/toolkit/ui/ui/properties.h; sourceTree = "<absolute>"; };
+		ED6581522CFF3CA000F5402F /* range.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = range.h; path = /Users/olaf/Projekte/toolkit/ui/ui/range.h; sourceTree = "<absolute>"; };
+		ED6581532CFF3CA000F5402F /* stock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stock.h; path = /Users/olaf/Projekte/toolkit/ui/ui/stock.h; sourceTree = "<absolute>"; };
+		ED6581542CFF3CA000F5402F /* text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = text.h; path = /Users/olaf/Projekte/toolkit/ui/ui/text.h; sourceTree = "<absolute>"; };
+		ED6581552CFF3CA000F5402F /* toolbar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = toolbar.h; path = /Users/olaf/Projekte/toolkit/ui/ui/toolbar.h; sourceTree = "<absolute>"; };
+		ED6581562CFF3CA000F5402F /* toolkit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = toolkit.h; path = /Users/olaf/Projekte/toolkit/ui/ui/toolkit.h; sourceTree = "<absolute>"; };
+		ED6581572CFF3CA000F5402F /* tree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tree.h; path = /Users/olaf/Projekte/toolkit/ui/ui/tree.h; sourceTree = "<absolute>"; };
+		ED6581582CFF3CA000F5402F /* ui.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ui.h; path = /Users/olaf/Projekte/toolkit/ui/ui/ui.h; sourceTree = "<absolute>"; };
+		ED6581592CFF3CA000F5402F /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = window.h; path = /Users/olaf/Projekte/toolkit/ui/ui/window.h; sourceTree = "<absolute>"; };
+		ED65815A2CFF3EE900F5402F /* MainWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainWindow.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/MainWindow.h; sourceTree = "<absolute>"; };
+		ED65815B2CFF3EE900F5402F /* MainWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MainWindow.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/MainWindow.m; sourceTree = "<absolute>"; };
+		ED65815D2CFF4BF200F5402F /* WindowManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WindowManager.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/WindowManager.h; sourceTree = "<absolute>"; };
+		ED65815E2CFF4BF200F5402F /* WindowManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WindowManager.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/WindowManager.m; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFileSystemSynchronizedRootGroup section */
+		ED6580AE2CFF122700F5402F /* toolkit */ = {
+			isa = PBXFileSystemSynchronizedRootGroup;
+			path = toolkit;
+			sourceTree = "<group>";
+		};
+/* End PBXFileSystemSynchronizedRootGroup section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		ED6580A92CFF122700F5402F /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		ED6580A32CFF122700F5402F = {
+			isa = PBXGroup;
+			children = (
+				ED6581472CFF3C8300F5402F /* public */,
+				ED65812E2CFF1A7200F5402F /* cocoa */,
+				ED6580F82CFF1A1200F5402F /* ucx */,
+				ED6580D92CFF19DB00F5402F /* common */,
+				ED6580AE2CFF122700F5402F /* toolkit */,
+				ED6580AD2CFF122700F5402F /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		ED6580AD2CFF122700F5402F /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				ED6580AC2CFF122700F5402F /* toolkit.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		ED6580D92CFF19DB00F5402F /* common */ = {
+			isa = PBXGroup;
+			children = (
+				ED6580DA2CFF19F900F5402F /* condvar.h */,
+				ED6580DB2CFF19F900F5402F /* condvar.c */,
+				ED6580DC2CFF19F900F5402F /* context.h */,
+				ED6580DD2CFF19F900F5402F /* context.c */,
+				ED6580DE2CFF19F900F5402F /* document.h */,
+				ED6580DF2CFF19F900F5402F /* document.c */,
+				ED6580E02CFF19F900F5402F /* menu.h */,
+				ED6580E12CFF19F900F5402F /* menu.c */,
+				ED6580E22CFF19F900F5402F /* object.h */,
+				ED6580E32CFF19F900F5402F /* object.c */,
+				ED6580E42CFF19F900F5402F /* properties.h */,
+				ED6580E52CFF19F900F5402F /* properties.c */,
+				ED6580E62CFF19F900F5402F /* threadpool.h */,
+				ED6580E72CFF19F900F5402F /* threadpool.c */,
+				ED6580E82CFF19F900F5402F /* toolbar.h */,
+				ED6580E92CFF19F900F5402F /* toolbar.c */,
+				ED6580EA2CFF19F900F5402F /* types.h */,
+				ED6580EB2CFF19F900F5402F /* types.c */,
+				ED6580EC2CFF19F900F5402F /* ucx_properties.h */,
+				ED6580ED2CFF19F900F5402F /* ucx_properties.c */,
+			);
+			path = common;
+			sourceTree = "<group>";
+		};
+		ED6580F82CFF1A1200F5402F /* ucx */ = {
+			isa = PBXGroup;
+			children = (
+				ED6580F92CFF1A3000F5402F /* allocator.c */,
+				ED6580FA2CFF1A3000F5402F /* array_list.c */,
+				ED6580FB2CFF1A3000F5402F /* buffer.c */,
+				ED6580FC2CFF1A3000F5402F /* compare.c */,
+				ED6581102CFF1A3000F5402F /* cx */,
+				ED6581112CFF1A3000F5402F /* hash_key.c */,
+				ED6581122CFF1A3000F5402F /* hash_map.c */,
+				ED6581132CFF1A3000F5402F /* iterator.c */,
+				ED6581142CFF1A3000F5402F /* linked_list.c */,
+				ED6581152CFF1A3000F5402F /* list.c */,
+				ED6581162CFF1A3000F5402F /* map.c */,
+				ED6581172CFF1A3000F5402F /* mempool.c */,
+				ED6581182CFF1A3000F5402F /* printf.c */,
+				ED6581192CFF1A3000F5402F /* string.c */,
+				ED65811B2CFF1A3000F5402F /* tree.c */,
+				ED65811C2CFF1A3000F5402F /* utils.c */,
+			);
+			path = ucx;
+			sourceTree = "<group>";
+		};
+		ED6581102CFF1A3000F5402F /* cx */ = {
+			isa = PBXGroup;
+			children = (
+				ED6580FD2CFF1A3000F5402F /* allocator.h */,
+				ED6580FE2CFF1A3000F5402F /* array_list.h */,
+				ED6580FF2CFF1A3000F5402F /* buffer.h */,
+				ED6581002CFF1A3000F5402F /* collection.h */,
+				ED6581012CFF1A3000F5402F /* common.h */,
+				ED6581022CFF1A3000F5402F /* common.h.orig */,
+				ED6581032CFF1A3000F5402F /* compare.h */,
+				ED6581042CFF1A3000F5402F /* hash_key.h */,
+				ED6581052CFF1A3000F5402F /* hash_map.h */,
+				ED6581062CFF1A3000F5402F /* iterator.h */,
+				ED6581072CFF1A3000F5402F /* linked_list.h */,
+				ED6581082CFF1A3000F5402F /* list.h */,
+				ED6581092CFF1A3000F5402F /* map.h */,
+				ED65810A2CFF1A3000F5402F /* mempool.h */,
+				ED65810B2CFF1A3000F5402F /* printf.h */,
+				ED65810C2CFF1A3000F5402F /* string.h */,
+				ED65810D2CFF1A3000F5402F /* test.h */,
+				ED65810E2CFF1A3000F5402F /* tree.h */,
+				ED65810F2CFF1A3000F5402F /* utils.h */,
+			);
+			name = cx;
+			path = /Users/olaf/Projekte/toolkit/ucx/cx;
+			sourceTree = "<absolute>";
+		};
+		ED65812E2CFF1A7200F5402F /* cocoa */ = {
+			isa = PBXGroup;
+			children = (
+				ED65815D2CFF4BF200F5402F /* WindowManager.h */,
+				ED65815E2CFF4BF200F5402F /* WindowManager.m */,
+				ED65815A2CFF3EE900F5402F /* MainWindow.h */,
+				ED65815B2CFF3EE900F5402F /* MainWindow.m */,
+				ED65813B2CFF3BCE00F5402F /* button.h */,
+				ED65813C2CFF3BCE00F5402F /* button.m */,
+				ED65813D2CFF3BCE00F5402F /* Container.h */,
+				ED65813E2CFF3BCE00F5402F /* Container.m */,
+				ED65813F2CFF3BCE00F5402F /* GridLayout.h */,
+				ED6581402CFF3BCE00F5402F /* GridLayout.m */,
+				ED6581412CFF3BCE00F5402F /* window.h */,
+				ED6581422CFF3BCE00F5402F /* window.m */,
+				ED6581352CFF287300F5402F /* EventData.h */,
+				ED6581362CFF287300F5402F /* EventData.m */,
+				ED6581372CFF287300F5402F /* UiJob.h */,
+				ED6581382CFF287300F5402F /* UiJob.m */,
+				ED6581322CFF1F1900F5402F /* AppDelegate.h */,
+				ED6581332CFF1F1900F5402F /* AppDelegate.m */,
+				ED65812F2CFF1A8800F5402F /* toolkit.h */,
+				ED6581302CFF1A8800F5402F /* toolkit.m */,
+			);
+			path = cocoa;
+			sourceTree = "<group>";
+		};
+		ED6581472CFF3C8300F5402F /* public */ = {
+			isa = PBXGroup;
+			children = (
+				ED6581482CFF3CA000F5402F /* button.h */,
+				ED6581492CFF3CA000F5402F /* container.h */,
+				ED65814A2CFF3CA000F5402F /* display.h */,
+				ED65814B2CFF3CA000F5402F /* dnd.h */,
+				ED65814C2CFF3CA000F5402F /* entry.h */,
+				ED65814D2CFF3CA000F5402F /* graphics.h */,
+				ED65814E2CFF3CA000F5402F /* icons.h */,
+				ED65814F2CFF3CA000F5402F /* image.h */,
+				ED6581502CFF3CA000F5402F /* menu.h */,
+				ED6581512CFF3CA000F5402F /* properties.h */,
+				ED6581522CFF3CA000F5402F /* range.h */,
+				ED6581532CFF3CA000F5402F /* stock.h */,
+				ED6581542CFF3CA000F5402F /* text.h */,
+				ED6581552CFF3CA000F5402F /* toolbar.h */,
+				ED6581562CFF3CA000F5402F /* toolkit.h */,
+				ED6581572CFF3CA000F5402F /* tree.h */,
+				ED6581582CFF3CA000F5402F /* ui.h */,
+				ED6581592CFF3CA000F5402F /* window.h */,
+			);
+			path = public;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		ED6580AB2CFF122700F5402F /* toolkit */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = ED6580BC2CFF122800F5402F /* Build configuration list for PBXNativeTarget "toolkit" */;
+			buildPhases = (
+				ED6580A82CFF122700F5402F /* Sources */,
+				ED6580A92CFF122700F5402F /* Frameworks */,
+				ED6580AA2CFF122700F5402F /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			fileSystemSynchronizedGroups = (
+				ED6580AE2CFF122700F5402F /* toolkit */,
+			);
+			name = toolkit;
+			packageProductDependencies = (
+			);
+			productName = toolkit;
+			productReference = ED6580AC2CFF122700F5402F /* toolkit.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		ED6580A42CFF122700F5402F /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				BuildIndependentTargetsInParallel = 1;
+				LastUpgradeCheck = 1610;
+				TargetAttributes = {
+					ED6580AB2CFF122700F5402F = {
+						CreatedOnToolsVersion = 16.1;
+					};
+				};
+			};
+			buildConfigurationList = ED6580A72CFF122700F5402F /* Build configuration list for PBXProject "toolkit" */;
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = ED6580A32CFF122700F5402F;
+			minimizedProjectReferenceProxies = 1;
+			preferredProjectObjectVersion = 77;
+			productRefGroup = ED6580AD2CFF122700F5402F /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				ED6580AB2CFF122700F5402F /* toolkit */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		ED6580AA2CFF122700F5402F /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				ED65812D2CFF1A3000F5402F /* common.h.orig in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		ED6580A82CFF122700F5402F /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				ED6580EE2CFF19F900F5402F /* context.c in Sources */,
+				ED6580EF2CFF19F900F5402F /* menu.c in Sources */,
+				ED6580F02CFF19F900F5402F /* threadpool.c in Sources */,
+				ED6580F12CFF19F900F5402F /* condvar.c in Sources */,
+				ED65815F2CFF4BF200F5402F /* WindowManager.m in Sources */,
+				ED6580F22CFF19F900F5402F /* document.c in Sources */,
+				ED65811D2CFF1A3000F5402F /* linked_list.c in Sources */,
+				ED65811E2CFF1A3000F5402F /* tree.c in Sources */,
+				ED6581202CFF1A3000F5402F /* mempool.c in Sources */,
+				ED6581212CFF1A3000F5402F /* map.c in Sources */,
+				ED6581222CFF1A3000F5402F /* hash_map.c in Sources */,
+				ED6581232CFF1A3000F5402F /* array_list.c in Sources */,
+				ED6581242CFF1A3000F5402F /* list.c in Sources */,
+				ED65815C2CFF3EE900F5402F /* MainWindow.m in Sources */,
+				ED6581252CFF1A3000F5402F /* compare.c in Sources */,
+				ED6581262CFF1A3000F5402F /* hash_key.c in Sources */,
+				ED6581272CFF1A3000F5402F /* iterator.c in Sources */,
+				ED6581282CFF1A3000F5402F /* string.c in Sources */,
+				ED6581312CFF1A8800F5402F /* toolkit.m in Sources */,
+				ED6581342CFF1F1900F5402F /* AppDelegate.m in Sources */,
+				ED6581292CFF1A3000F5402F /* allocator.c in Sources */,
+				ED6581432CFF3BCE00F5402F /* window.m in Sources */,
+				ED6581442CFF3BCE00F5402F /* button.m in Sources */,
+				ED6581452CFF3BCE00F5402F /* Container.m in Sources */,
+				ED6581462CFF3BCE00F5402F /* GridLayout.m in Sources */,
+				ED65812A2CFF1A3000F5402F /* utils.c in Sources */,
+				ED6581392CFF287300F5402F /* EventData.m in Sources */,
+				ED65813A2CFF287300F5402F /* UiJob.m in Sources */,
+				ED65812B2CFF1A3000F5402F /* buffer.c in Sources */,
+				ED65812C2CFF1A3000F5402F /* printf.c in Sources */,
+				ED6580F32CFF19F900F5402F /* object.c in Sources */,
+				ED6580F42CFF19F900F5402F /* toolbar.c in Sources */,
+				ED6580F52CFF19F900F5402F /* types.c in Sources */,
+				ED6580F62CFF19F900F5402F /* properties.c in Sources */,
+				ED6580F72CFF19F900F5402F /* ucx_properties.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		ED6580BA2CFF122800F5402F /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				ENABLE_USER_SCRIPT_SANDBOXING = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu17;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = ../../../ucx;
+				LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+				MACOSX_DEPLOYMENT_TARGET = 15.1;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		ED6580BB2CFF122800F5402F /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_USER_SCRIPT_SANDBOXING = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu17;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = ../../../ucx;
+				LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+				MACOSX_DEPLOYMENT_TARGET = 15.1;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		ED6580BD2CFF122800F5402F /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = toolkit/toolkit.entitlements;
+				CODE_SIGN_STYLE = Manual;
+				COMBINE_HIDPI_IMAGES = YES;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = "";
+				GENERATE_INFOPLIST_FILE = YES;
+				HEADER_SEARCH_PATHS = (
+					../../../ucx,
+					../../../ui,
+				);
+				INFOPLIST_KEY_NSHumanReadableCopyright = "";
+				INFOPLIST_KEY_NSMainNibFile = MainMenu;
+				INFOPLIST_KEY_NSPrincipalClass = NSApplication;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				OTHER_CFLAGS = "-DUI_COCOA";
+				PRODUCT_BUNDLE_IDENTIFIER = de.unixwork.toolkit;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+			};
+			name = Debug;
+		};
+		ED6580BE2CFF122800F5402F /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = toolkit/toolkit.entitlements;
+				CODE_SIGN_STYLE = Manual;
+				COMBINE_HIDPI_IMAGES = YES;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = "";
+				GENERATE_INFOPLIST_FILE = YES;
+				HEADER_SEARCH_PATHS = (
+					../../../ucx,
+					../../../ui,
+				);
+				INFOPLIST_KEY_NSHumanReadableCopyright = "";
+				INFOPLIST_KEY_NSMainNibFile = MainMenu;
+				INFOPLIST_KEY_NSPrincipalClass = NSApplication;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				OTHER_CFLAGS = "-DUI_COCOA";
+				PRODUCT_BUNDLE_IDENTIFIER = de.unixwork.toolkit;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		ED6580A72CFF122700F5402F /* Build configuration list for PBXProject "toolkit" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				ED6580BA2CFF122800F5402F /* Debug */,
+				ED6580BB2CFF122800F5402F /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		ED6580BC2CFF122800F5402F /* Build configuration list for PBXNativeTarget "toolkit" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				ED6580BD2CFF122800F5402F /* Debug */,
+				ED6580BE2CFF122800F5402F /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = ED6580A42CFF122700F5402F /* Project object */;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit.xcodeproj/project.xcworkspace/contents.xcworkspacedata	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit.xcodeproj/xcshareddata/xcschemes/toolkit.xcscheme	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1610"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "ED6580AB2CFF122700F5402F"
+               BuildableName = "toolkit.app"
+               BlueprintName = "toolkit"
+               ReferencedContainer = "container:toolkit.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "ED6580AB2CFF122700F5402F"
+            BuildableName = "toolkit.app"
+            BlueprintName = "toolkit"
+            ReferencedContainer = "container:toolkit.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "ED6580AB2CFF122700F5402F"
+            BuildableName = "toolkit.app"
+            BlueprintName = "toolkit"
+            ReferencedContainer = "container:toolkit.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit/Assets.xcassets/AccentColor.colorset/Contents.json	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,11 @@
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit/Assets.xcassets/AppIcon.appiconset/Contents.json	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,58 @@
+{
+  "images" : [
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "16x16"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "16x16"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "32x32"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "32x32"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "128x128"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "128x128"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "256x256"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "256x256"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "1x",
+      "size" : "512x512"
+    },
+    {
+      "idiom" : "mac",
+      "scale" : "2x",
+      "size" : "512x512"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit/Assets.xcassets/Contents.json	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit/Base.lproj/MainMenu.xib	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="23504" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23504"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+            <connections>
+                <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
+        <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
+        <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+            <items>
+                <menuItem title="toolkit" id="1Xt-HY-uBw">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="toolkit" systemMenu="apple" id="uQy-DD-JDr">
+                        <items>
+                            <menuItem title="About toolkit" id="5kV-Vb-QxS">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+                            <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
+                            <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
+                            <menuItem title="Services" id="NMo-om-nkz">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
+                            <menuItem title="Hide toolkit" keyEquivalent="h" id="Olw-nP-bQN">
+                                <connections>
+                                    <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+                                <connections>
+                                    <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem title="Show All" id="Kd2-mp-pUS">
+                                <modifierMask key="keyEquivalentModifierMask"/>
+                                <connections>
+                                    <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
+                                </connections>
+                            </menuItem>
+                            <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+                            <menuItem title="Quit toolkit" keyEquivalent="q" id="4sb-4s-VLi">
+                                <connections>
+                                    <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+                <menuItem title="File" id="dMs-cI-mzQ">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                </menuItem>
+                <menuItem title="Edit" id="5QF-Oa-p0T">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                </menuItem>
+                <menuItem title="Format" id="jxT-CU-nIS">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                </menuItem>
+                <menuItem title="View" id="H8h-7b-M4v">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                </menuItem>
+                <menuItem title="Window" id="aUF-d1-5bR">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                </menuItem>
+                <menuItem title="Help" id="wpr-3q-Mcd">
+                    <modifierMask key="keyEquivalentModifierMask"/>
+                    <menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
+                        <items>
+                            <menuItem title="toolkit Help" keyEquivalent="?" id="FKE-Sm-Kum">
+                                <connections>
+                                    <action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
+                                </connections>
+                            </menuItem>
+                        </items>
+                    </menu>
+                </menuItem>
+            </items>
+            <point key="canvasLocation" x="200" y="121"/>
+        </menu>
+    </objects>
+</document>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit/main.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,58 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+#include <ui/ui.h>
+
+static void action_button(UiEvent *event, void *userdata) {
+    printf("button click\n");
+}
+
+void application_startup(UiEvent *event, void *data) {
+    UiObject *obj = ui_window("My Window", NULL);
+    
+    
+    ui_button(obj, .label = "Button X1 -------------------------------------------------- END", .onclick = action_button);
+    ui_newline(obj);
+    ui_button(obj, .label = "Button X2");
+    ui_button(obj, .label = "Button X3", .hexpand = TRUE);
+    ui_button(obj, .label = "Button X4");
+    ui_newline(obj);
+    ui_button(obj, .label = "Button X5");
+    
+    
+    ui_show(obj);
+}
+
+int main(int argc, char * argv[]) {
+    ui_init("app1", argc, argv);
+    ui_onstartup(application_startup, NULL);
+    ui_main();
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/xcode/toolkit/toolkit/toolkit.entitlements	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.app-sandbox</key>
+	<false/>
+	<key>com.apple.security.files.user-selected.read-only</key>
+	<true/>
+</dict>
+</plist>
--- a/resource/template.app/Contents/Info.plist	Sat Nov 30 20:33:16 2024 +0100
+++ b/resource/template.app/Contents/Info.plist	Wed Dec 04 08:55:49 2024 +0100
@@ -3,13 +3,13 @@
 <plist version="1.0">
 <dict>
 	<key>BuildMachineOSBuild</key>
-	<string>10K549</string>
+	<string>24B91</string>
 	<key>CFBundleDevelopmentRegion</key>
-	<string>de_DE</string>
+	<string>en</string>
 	<key>CFBundleExecutable</key>
 	<string>mk12</string>
 	<key>CFBundleIdentifier</key>
-	<string>com.yourcompany.toolkit</string>
+	<string>de.unixwork.toolkit</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundleName</key>
@@ -18,53 +18,32 @@
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
 	<string>1.0</string>
-	<key>CFBundleSignature</key>
-	<string>????</string>
+	<key>CFBundleSupportedPlatforms</key>
+	<array>
+		<string>MacOSX</string>
+	</array>
 	<key>CFBundleVersion</key>
 	<string>1</string>
 	<key>DTCompiler</key>
-	<string></string>
+	<string>com.apple.compilers.llvm.clang.1_0</string>
 	<key>DTPlatformBuild</key>
-	<string>10M2518</string>
+	<string>24B75</string>
+	<key>DTPlatformName</key>
+	<string>macosx</string>
 	<key>DTPlatformVersion</key>
-	<string>PG</string>
+	<string>15.1</string>
 	<key>DTSDKBuild</key>
-	<string>10M2518</string>
+	<string>24B75</string>
 	<key>DTSDKName</key>
-	<string>macosx10.6</string>
+	<string>macosx15.1</string>
 	<key>DTXcode</key>
-	<string>0400</string>
+	<string>1610</string>
 	<key>DTXcodeBuild</key>
-	<string>10M2518</string>
+	<string>16B40</string>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.7</string>
+	<string>15.1</string>
 	<key>NSMainNibFile</key>
 	<string>MainMenu</string>
-	<key>CFBundleDisplayName</key>
-	<string></string>
-	<key>CFBundleGetInfoString</key>
-	<string></string>
-	<key>LSApplicationCategoryType</key>
-	<string></string>
-	<key>CFBundleDocumentTypes</key>
-	<array>
-		<dict>
-			<key>LSItemContentTypes</key>
-			<array>
-				<string>public.data</string>
-			</array>
-			<key>CFBundleTypeIconFile</key>
-			<string></string>
-			<key>CFBundleTypeName</key>
-			<string>DocumentType</string>
-			<key>CFBundleTypeRole</key>
-			<string>Editor</string>
-<!--
-			<key>NSDocumentClass</key>
-			<string>Document</string>
--->
-		</dict>
-	</array>
 	<key>NSPrincipalClass</key>
 	<string>NSApplication</string>
 </dict>
Binary file resource/template.app/Contents/Resources/Base.lproj/MainMenu.nib has changed
Binary file resource/template.app/Contents/Resources/English.lproj/InfoPlist.strings has changed
Binary file resource/template.app/Contents/Resources/English.lproj/MainMenu.nib has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/EventData.h	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,43 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "../ui/toolkit.h"
+#import "../common/context.h"
+
+@interface EventData : NSObject
+@property UiObject    *obj;
+@property ui_callback callback;
+@property void        *userdata;
+@property void        *data;
+@property int         value;
+
+- (EventData*)init:(ui_callback)cb userdata:(void*)userdata;
+
+- (void)handleEvent:(id)sender;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/EventData.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,52 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "EventData.h"
+
+@implementation EventData
+
+- (EventData*)init:(ui_callback)cb userdata:(void*)userdata {
+    _callback = cb;
+    _userdata = userdata;
+    return self;
+}
+
+- (void)handleEvent:(id)sender {
+    if(self.callback) {
+        UiEvent event;
+        event.obj = self.obj;
+        event.window = event.obj->window;
+        event.document = event.obj->ctx->document;
+        event.eventdata = self.data;
+        event.intval = self.value;
+        self.callback(&event, self.userdata);
+    }
+}
+
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/GridLayout.h	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,71 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+
+#import "Container.h"
+
+#import <cx/array_list.h>
+
+typedef struct GridElm {
+    NSView *view;
+    int margin;
+    int x;
+    int y;
+    int colspan;
+    int rowspan;
+    BOOL hexpand;
+    BOOL vexpand;
+    BOOL hfill;
+    BOOL vfill;
+} GridElm;
+
+typedef struct GridDef {
+    int size;
+    int pos;
+    int preferred_size;
+    BOOL extend;
+} GridDef;
+
+@interface GridLayout : NSView<Container>
+
+@property int columnspacing;
+@property int rowspacing;
+@property CxList *children;
+@property NSSize preferredSize;
+
+@property NSButton *test;
+
+@property int x;
+@property int y;
+@property int cols;
+@property int rows;
+
+- (GridLayout*)init;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/GridLayout.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,214 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "GridLayout.h"
+
+
+
+@implementation GridLayout
+
+@synthesize label=_label;
+@synthesize uilayout=_uilayout;
+@synthesize newline=_newline;
+
+- (GridLayout*)init {
+    self = [super init];
+    _columnspacing = 0;
+    _rowspacing = 0;
+    _children = cxArrayListCreateSimple(sizeof(GridElm), 32);
+    
+    return self;
+}
+
+/*
+- (void) layout {
+    [super layout];
+    
+    NSRect r1 = _test.frame;
+    NSSize s1 = _test.intrinsicContentSize;
+    NSEdgeInsets e1 = _test.alignmentRectInsets;
+    
+    printf("fuck\n");
+}
+ */
+
+
+- (void) layout {
+    int ncols = _cols+1;
+    int nrows = _rows+1;
+    
+    GridDef *coldef = calloc(ncols, sizeof(GridDef));
+    GridDef *rowdef = calloc(nrows, sizeof(GridDef));
+    
+    NSRect viewFrame = self.frame;
+    
+    int colspacing = _columnspacing;
+    int rowspacing = _rowspacing;
+    
+    CxIterator i = cxListIterator(_children);
+    cx_foreach(GridElm *, elm, i) {
+        NSSize size = elm->view.intrinsicContentSize;
+        NSEdgeInsets alignment = elm->view.alignmentRectInsets;
+        if(size.width != NSViewNoIntrinsicMetric) {
+            CGFloat width = size.width + alignment.left + alignment.right;
+            if(width > coldef[elm->x].preferred_size) {
+                coldef[elm->x].preferred_size = width;
+            }
+        }
+        if(size.height != NSViewNoIntrinsicMetric) {
+            CGFloat height = size.height + alignment.top + alignment.right;
+            //CGFloat height = size.height;
+            if(height > rowdef[elm->y].preferred_size) {
+                rowdef[elm->y].preferred_size = height;
+            }
+        }
+        
+        if(elm->hexpand) {
+            coldef[elm->x].extend = TRUE;
+        }
+        if(elm->vexpand) {
+            rowdef[elm->y].extend = TRUE;
+        }
+    }
+    
+    int col_ext = 0;
+    int row_ext = 0;
+    
+    int preferred_width = 0;
+    int preferred_height = 0;
+    for(int j=0;j<ncols;j++) {
+        preferred_width += coldef[j].preferred_size + colspacing;
+        if(coldef[j].extend) {
+            col_ext++;
+        }
+    }
+    for(int j=0;j<nrows;j++) {
+        preferred_height += rowdef[j].preferred_size + rowspacing;
+        if(rowdef[j].extend) {
+            row_ext++;
+        }
+    }
+    
+    _preferredSize.width = preferred_width;
+    _preferredSize.height = preferred_height;
+    
+    
+    int hremaining = viewFrame.size.width - preferred_width;
+    int vremaining = viewFrame.size.height - preferred_height;
+    int hext = hremaining/col_ext;
+    int vext = vremaining/row_ext;
+    
+    for(int j=0;j<ncols;j++) {
+        GridDef *col = &coldef[j];
+        if(col->extend) {
+            col->size = col->preferred_size + hext;
+        } else {
+            col->size = col->preferred_size;
+        }
+    }
+    for(int j=0;j<nrows;j++) {
+        GridDef *row = &rowdef[j];
+        if(row->extend) {
+            row->size = row->preferred_size + vext;
+        } else {
+            row->size = row->preferred_size;
+        }
+    }
+    
+    int pos = 0;
+    for(int j=0;j<ncols;j++) {
+        coldef[j].pos = pos;
+        pos += coldef[j].size + colspacing;
+    }
+    pos = 0;
+    for(int j=0;j<nrows;j++) {
+        rowdef[j].pos = pos;
+        pos += rowdef[j].size + rowspacing;
+    }
+    
+    i = cxListIterator(_children);
+    cx_foreach(GridElm *, elm, i) {
+        //NSSize size = elm->view.intrinsicContentSize;
+        GridDef *col = &coldef[elm->x];
+        GridDef *row = &rowdef[elm->y];
+        
+        NSEdgeInsets alignment = elm->view.alignmentRectInsets;
+        NSRect frame;
+        frame.size.width = col->size;
+        frame.size.height = row->size;
+        frame.origin.x = col->pos - (alignment.left+alignment.right)/2;
+        frame.origin.y = viewFrame.size.height - row->pos - frame.size.height + ((alignment.top+alignment.right)/2);
+        elm->view.frame = frame;
+    }
+    
+    free(coldef);
+    free(rowdef);
+}
+ 
+
+- (NSSize)intrinsicContentSize {
+    return self.preferredSize;
+}
+
+- (void) addView:(NSView*)view fill:(BOOL)fill {
+    if(_newline) {
+        _y++;
+        _x = 0;
+        _newline = FALSE;
+    }
+    
+    GridElm elm;
+    elm.x = _x;
+    elm.y = _y;
+    elm.margin = 0;
+    elm.colspan = _uilayout.colspan;
+    elm.rowspan = _uilayout.rowspan;
+    elm.hfill = _uilayout.hfill;
+    elm.vfill = _uilayout.vfill;
+    elm.hexpand = _uilayout.hexpand;
+    elm.vexpand = _uilayout.vexpand;
+    elm.view = view;
+    cxListAdd(_children, &elm);
+    
+    [self addSubview:view];
+    self.needsLayout = YES;
+    
+    if(_x > _cols) {
+        _cols = _x;
+    }
+    if(_y > _rows) {
+        _rows = _y;
+    }
+    _x++;
+}
+
+- (void) dealloc {
+    cxListDestroy(_children);
+}
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/MainWindow.h	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,38 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+#import "../ui/window.h"
+
+@interface MainWindow : NSWindow
+
+@property UiObject *uiobj;
+
+- (MainWindow*)init:(UiObject*)obj;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/MainWindow.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,65 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "MainWindow.h"
+#import "Container.h"
+#import "GridLayout.h"
+#import "../common/object.h"
+
+@implementation MainWindow
+
+- (MainWindow*)init:(UiObject*)obj {
+    self.uiobj = obj;
+    NSRect frame = NSMakeRect(300, 200, 600, 500);
+    
+    self = [self initWithContentRect:frame
+                           styleMask:NSWindowStyleMaskTitled |
+            NSWindowStyleMaskResizable |
+            NSWindowStyleMaskClosable |
+            NSWindowStyleMaskMiniaturizable
+                             backing:NSBackingStoreBuffered
+                               defer:false];
+    
+    // create a vertical stackview as default container
+    //BoxContainer *vbox = [[BoxContainer alloc] init:NSUserInterfaceLayoutOrientationVertical spacing:0];
+    GridLayout *vbox = [[GridLayout alloc] init];
+    vbox.translatesAutoresizingMaskIntoConstraints = false;
+    [self.contentView addSubview:vbox];
+    [NSLayoutConstraint activateConstraints:@[
+        [vbox.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:4],
+        [vbox.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
+        [vbox.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor],
+        [vbox.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor]
+    ]];
+    
+    uic_object_push_container(obj, ui_create_container(obj, vbox));
+    
+    return self;
+}
+
+@end
--- a/ui/cocoa/Makefile	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/Makefile	Wed Dec 04 08:55:49 2024 +0100
@@ -27,7 +27,7 @@
 #
 
 $(COCOA_OBJPRE)%.o: cocoa/%.m
-	$(CC) -o $@ -c $(CFLAGS) $<
+	$(CC) -o $@ -c -I../ucx -fobjc-arc $(CFLAGS) $(TK_CFLAGS) $<
 
 $(UI_LIB): $(OBJ)
 	$(AR) $(ARFLAGS) $(UI_LIB) $(OBJ)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/UiJob.h	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,30 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/UiJob.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,29 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "UiJob.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/WindowManager.h	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,41 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+
+@interface WindowManager : NSObject<NSWindowDelegate>
+
+@property NSMutableArray<NSWindow*> *windows;
+
++ (WindowManager*) sharedWindowManager;
+
+- (WindowManager*)init;
+
+- (void)addWindow:(NSWindow*)win;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/WindowManager.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,57 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WindowManager.h"
+
+@implementation WindowManager
+
+static WindowManager *instance = nil;
+
++ (WindowManager*) sharedWindowManager {
+    if(instance == nil) {
+        instance = [[WindowManager alloc] init];
+    }
+    return instance;
+}
+
+- (WindowManager*)init {
+    _windows = [[NSMutableArray alloc] initWithCapacity:16];
+    return self;
+}
+
+- (void)addWindow:(NSWindow*)win {
+    [_windows addObject:win];
+    [win setDelegate:self];
+}
+
+- (void) windowWillClose:(NSNotification *) notification {
+    NSWindow *window = notification.object;
+    [_windows removeObject:window];
+}
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/appdelegate.h	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,37 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "../ui/toolkit.h"
+#include "../common/context.h"
+#include "../common/object.h"
+
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/appdelegate.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,49 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "AppDelegate.h"
+
+#import "toolkit.h"
+
+@implementation AppDelegate
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+    ui_cocoa_onstartup();
+}
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
+    ui_cocoa_onexit();
+}
+
+
+- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
+    return YES;
+}
+
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/button.h	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,31 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+
+#import "../ui/button.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/button.m	Wed Dec 04 08:55:49 2024 +0100
@@ -0,0 +1,53 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "button.h"
+#import "EventData.h"
+#import "Container.h"
+#import <objc/runtime.h>
+
+UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args) {
+    NSButton *button = [[NSButton alloc] init];
+    if(args.label) {
+        NSString *label = [[NSString alloc] initWithUTF8String:args.label];
+        button.title = label;
+    }
+    
+    if(args.onclick) {
+        EventData *event = [[EventData alloc] init:args.onclick userdata:args.onclickdata];
+        event.obj = obj;
+        button.target = event;
+        button.action = @selector(handleEvent:);
+        objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+    }
+    
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, button, &layout, FALSE);
+    
+    return (__bridge void*)button;
+}
--- a/ui/cocoa/container.h	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/container.h	Wed Dec 04 08:55:49 2024 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -26,19 +26,65 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "../ui/toolkit.h"
 #import "toolkit.h"
 
-typedef void(*ui_container_add_f)(UiContainer*, NSView*);
+#import "../ui/container.h"
+
+#define ui_lb2bool(b) ((b) == UI_LAYOUT_TRUE ? TRUE : FALSE)
+#define ui_bool2lb(b) ((b) ? UI_LAYOUT_TRUE : UI_LAYOUT_FALSE)
+
+typedef struct UiLayout UiLayout;
+typedef enum UiLayoutBool UiLayoutBool;
 
-struct UiContainer {
-    NSView* widget;
-    void   (*add)(UiContainer*, NSView*);
-    NSRect (*getframe)(UiContainer*);
+enum UiLayoutBool {
+    UI_LAYOUT_UNDEFINED = 0,
+    UI_LAYOUT_TRUE,
+    UI_LAYOUT_FALSE,
+};
+
+struct UiLayout {
+    UiTri        fill;
+    //UiBool       newline;
+    //char         *label;
+    UiBool       hexpand;
+    UiBool       vexpand;
+    UiBool       hfill;
+    UiBool       vfill;
+    //int          width;
+    int          colspan;
+    int          rowspan;
 };
 
-UiContainer* ui_window_container(UiObject *obj, NSWindow *window);
+#define UI_INIT_LAYOUT(args) (UiLayout) {\
+    .fill = args.fill, \
+    .hexpand = args.hexpand, \
+    .vexpand = args.vexpand, \
+    .hfill = args.hfill, \
+    .vfill = args.vfill, \
+    .colspan = args.colspan, \
+    .rowspan = args.rowspan }
+
+
+@protocol Container
+
+@property UiLayout uilayout;
+@property const char *label;
+@property UiBool newline;
 
-NSRect ui_container_getframe(UiContainer *ct);
-void ui_container_add(UiContainer *ct, NSView *view);
+- (void) addView:(NSView*)view fill:(BOOL)fill;
+
+@end
+
+@interface BoxContainer : NSStackView<Container>
+
+- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing;
 
+@end
+
+
+
+
+
+UiContainerX* ui_create_container(UiObject *obj, id<Container> container);
+
+void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout, UiBool fill);
--- a/ui/cocoa/container.m	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/container.m	Wed Dec 04 08:55:49 2024 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -26,81 +26,143 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <stdio.h>
-#import <stdlib.h>
+#import "Container.h"
+#import "GridLayout.h"
+
+/* ------------------------- container classes ------------------------- */
 
-#import "container.h"
+@implementation BoxContainer
 
+@synthesize label=_label;
+@synthesize uilayout=_uilayout;
+@synthesize newline=_newline;
 
-UiContainer* ui_window_container(UiObject *obj, NSWindow *window) {
-    UiContainer *ct = ucx_mempool_malloc(
-                                         obj->ctx->mempool,
-                                         sizeof(UiContainer));
-    ct->widget = [window contentView];
-    ct->add = ui_container_add;
-    ct->getframe = ui_container_getframe;
-    return ct;
+- (BoxContainer*)init:(NSUserInterfaceLayoutOrientation)orientation spacing:(int)spacing {
+    self = [super init];
+    _label = NULL;
+    _uilayout = (UiLayout){ 0 };
+    _newline = false;
+    
+    self.distribution = NSStackViewDistributionFillProportionally;
+    self.spacing = spacing;
+    
+    self.orientation = orientation;
+    if(orientation == NSUserInterfaceLayoutOrientationHorizontal) {
+        self.alignment = NSLayoutAttributeHeight;
+    } else {
+        self.alignment = NSLayoutAttributeWidth;
+    }
+    
+    
+    return self;
 }
 
-UIWIDGET ui_sidebar(UiObject *obj) {
-    UiContainer *ct = uic_get_current_container(obj);
-    NSRect frame = ct->getframe(ct);
+- (void) addView:(NSView*)view fill:(BOOL)fill {
+    if(_uilayout.fill != UI_LAYOUT_UNDEFINED) {
+        fill = ui_lb2bool(_uilayout.fill);
+    }
     
-    // create and add views
-    NSSplitView *splitview = [[NSSplitView alloc] initWithFrame:frame];
-    [splitview setVertical:YES];
-    [splitview setDividerStyle:NSSplitViewDividerStyleThin];
-    ct->add(ct, splitview);
+    [self addArrangedSubview:view];
     
-    NSRect lframe;
-    lframe.origin.x = 0;
-    lframe.origin.y = 0;
-    lframe.size.width = 200;
-    lframe.size.height = frame.size.height;
-    
-    NSRect rframe;
-    rframe.origin.x = 0;
-    rframe.origin.y = 0;
-    rframe.size.width = frame.size.width - 201;
-    rframe.size.height = frame.size.height;
-    
-    NSView *sidebar = [[NSView alloc]initWithFrame:lframe];
-    NSView *contentarea = [[NSView alloc]initWithFrame:rframe];
+    if(self.orientation == NSUserInterfaceLayoutOrientationHorizontal) {
+        [view.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES;
+        if(!fill) {
+            [view.widthAnchor constraintEqualToConstant:view.intrinsicContentSize.width].active = YES;
+        }
+    } else {
+        [view.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES;
+        if(!fill) {
+            [view.heightAnchor constraintEqualToConstant:view.intrinsicContentSize.height].active = YES;
+        }
+    }
     
-    [splitview addSubview:sidebar];
-    [splitview addSubview:contentarea];
+    // at the moment, only the fill layout option needs to be reset
+    _uilayout.fill = UI_DEFAULT;
+}
+
+@end
+
+
+
+/* -------------------- public container functions --------------------- */
+
+static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, NSUserInterfaceLayoutOrientation orientation) {
+    BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args.spacing];
+    box.translatesAutoresizingMaskIntoConstraints = false;
     
-    // add ui objects for the sidebar and contentarea
-    // the sidebar is added last, so that new views are added first to it
-    UiObject *left = uic_object_new(obj, sidebar);
-    UiContainer *ct1 = ucx_mempool_malloc(
-            obj->ctx->mempool,
-            sizeof(UiContainer));
-    ct1->widget = sidebar;
-    ct1->add = ui_container_add;
-    ct1->getframe = ui_container_getframe;
-    left->container = ct1;
+    // add box to the parent
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, box, &layout, TRUE);
+    
+    // add new box to the obj container chain
+    uic_object_push_container(obj, ui_create_container(obj, box));
     
-    UiObject *right = uic_object_new(obj, sidebar);
-    UiContainer *ct2 = ucx_mempool_malloc(
-            obj->ctx->mempool,
-            sizeof(UiContainer));
-    ct2->widget = contentarea;
-    ct2->add = ui_container_add;
-    ct2->getframe = ui_container_getframe;
-    right->container = ct2;
+    return (__bridge void*)box;
+}
+
+UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) {
+    return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationVertical);
+}
+
+UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) {
+    return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationHorizontal);
+}
+
+UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) {
+    GridLayout *grid = [[GridLayout alloc] init];
+    grid.translatesAutoresizingMaskIntoConstraints = false;
     
-    uic_obj_add(obj, right);
-    uic_obj_add(obj, left);
+    // add box to the parent
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, grid, &layout, TRUE);
     
-    return splitview;
+    // add new box to the obj container chain
+    uic_object_push_container(obj, ui_create_container(obj, grid));
+    
+    return (__bridge void*)grid;
 }
 
 
-NSRect ui_container_getframe(UiContainer *ct) {
-    return [ct->widget frame];
+void ui_container_begin_close(UiObject *obj) {
+    UiContainerX *ct = obj->container_end;
+    ct->close = 1;
+}
+
+int ui_container_finish(UiObject *obj) {
+    UiContainerX *ct = obj->container_end;
+    if(ct->close) {
+        ui_end_new(obj);
+        return 0;
+    }
+    return 1;
 }
 
-void ui_container_add(UiContainer *ct, NSView *view) {
-    [ct->widget addSubview: view];
+/* ------------------------- private functions ------------------------- */
+
+UiContainerX* ui_create_container(UiObject *obj, id<Container> container) {
+    UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX));
+    ctn->container = (__bridge void*)container;
+    ctn->close = 0;
+    ctn->prev = NULL;
+    ctn->next = NULL;
+    return ctn;
 }
+
+void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout, UiBool fill) {
+    UiContainerX *ctn = obj->container_end;
+    id<Container> container = (__bridge id<Container>)ctn->container;
+    container.uilayout = *layout;
+    [container addView:view fill:fill];
+}
+
+/* ---------------------- public layout functions ----------------------- */
+
+void ui_newline(UiObject *obj) {
+    UiContainerX *ctn = obj->container_end;
+    if(ctn) {
+        id<Container> container = (__bridge id<Container>)ctn->container;
+        container.newline = TRUE;
+    } else {
+        fprintf(stderr, "Error: obj has no container\n");
+    }
+}
--- a/ui/cocoa/graphics.h	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "../ui/graphics.h"
-#import "toolkit.h"
-
-
-@interface UiCanvas : NSView {
-    UiObject            *object;
-    ui_drawfunc         callback;
-    void                *userdata;
-}
-
-- (UiObject*) object;
-- (void) setObject:(void*)obj;
-
-- (void*) userdata;
-- (void) setUserdata:(void*)d;
-
-- (ui_drawfunc) callback;
-- (void) setCallback: (ui_drawfunc)f;
-
-
-- (void)drawRect:(NSRect)rect;
-
-@end
-
--- a/ui/cocoa/graphics.m	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import <stdio.h>
-#import <stdlib.h>
-#import <string.h>
-
-#import "graphics.h"
-#import "container.h"
-#import "../common/context.h"
-
-
-
-@implementation UiCanvas
-
-- (UiObject*) object {
-    return object;
-}
-
-- (void) setObject:(void*)obj {
-    object = obj;
-}
-
-- (void*) userdata {
-    return userdata;
-}
-
-- (void) setUserdata:(void*)d {
-    userdata = d;
-}
-
-- (ui_drawfunc) callback {
-    return callback;
-}
-- (void) setCallback: (ui_drawfunc)f {
-    callback = f;
-}
-
-- (void) drawRect:(NSRect)rect {
-    UiGraphics g;
-    NSRect bounds = [self bounds];
-    g.width = bounds.size.width;
-    g.height = bounds.size.height;
-    
-    UiEvent ev;
-    ev.obj = object;
-    ev.window = object->window;
-    ev.document = object->ctx->document;
-    
-    callback(&ev, &g, userdata);
-}
-
-@end
-
-
-UIWIDGET ui_drawingarea(UiObject *obj, ui_drawfunc f, void *userdata) {
-    UiContainer *ct = uic_get_current_container(obj);
-    
-    NSRect frame = ct->getframe(ct);
-    
-    UiCanvas *canvas = [[UiCanvas alloc]initWithFrame:frame];
-    [canvas setObject: obj];
-    [canvas setCallback: f];
-    [canvas setUserdata: userdata];
-    ct->add(ct, canvas);
-    
-    return canvas;
-}
-
-
-// drawing functions
-void ui_graphics_color(UiGraphics *gr, int red, int green, int blue) {
-    float r = ((float)red) / 255.f;
-    float g = ((float)green) / 255.f;
-    float b = ((float)blue) / 255.f;
-    
-    NSColor *color = [NSColor colorWithCalibratedRed:r green:g blue:b alpha:1];
-    [color set];
-}
-
-void ui_draw_rect(UiGraphics *g, int x, int y, int w, int h, int fill) {
-    // translate y
-    y = g->height - y - h;
-    
-    NSRect bounds;
-    bounds.origin.x = x;
-    bounds.origin.y = y;
-    bounds.size.width = w;
-    bounds.size.height = h;
-    
-    if(fill) {
-        NSRectFill(bounds);
-    } else {
-        NSFrameRect(bounds);
-    }
-}
-
-
-
--- a/ui/cocoa/menu.h	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "../ui/menu.h"
-#import "toolkit.h"
-#import <ucx/list.h>
-
-typedef struct UiAbstractMenuItem {
-    int  (*update)(id window, void *item);
-    void *item_data;
-} UiAbstractMenuItem;
-
-typedef struct UiMenuItem {
-    NSMenuItem  *item;
-    int         state;
-} UiMenuItem;
-
-typedef struct UiStateItem {
-    NSMenuItem  *item;
-    char        *var;
-} UiStateItem;
-
-typedef struct UiMenuItemList {
-    NSMenu      *menu;
-    NSMenuItem  *first;
-    UiList      *list;
-    int         index;
-    int         oldcount;
-    ui_callback callback;
-    void        *data;
-} UiMenuItemList;
-
-@interface UiMenuDelegate : NSObject <NSMenuDelegate> {
-    UcxList *items; // UiStateItem*
-    UcxList *itemlists; // UiMenuItemList*
-}
-
-- (void) menuNeedsUpdate:(NSMenu*) menu;
-
-- (void) addItem:(NSMenuItem*) item var: (char*)name;
-
-- (void) addList:(UiList*) list menu:(NSMenu*)menu index: (int)i callback: (ui_callback)f data:(void*) data;
-
-- (UcxList*) items;
-
-- (UcxList*) lists;
-
-@end
-
-@interface UiGroupMenuItem : NSMenuItem {
-    NSMutableArray *groups;
-}
-
-- (id)initWithTitle:(NSString*)title action:(SEL)action keyEquivalent:(NSString*)s;
-
-- (void) addGroup:(int)group;
-
-- (void) checkGroups:(int*)g count:(int)n;
-
-@end
-
-void ui_menu_init();
-UiMenuDelegate* ui_menu_delegate();
-
-int ui_menuitem_get(UiInteger *i);
-void ui_menuitem_set(UiInteger *i, int value);
-
-int ui_update_item(id window, void *data);
-int ui_update_item_list(id window, void *data);
--- a/ui/cocoa/menu.m	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,319 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import <stdio.h>
-#import <stdlib.h>
-#import <string.h>
-#import <stdarg.h>
-
-#import "menu.h"
-#import "window.h"
-#import "stock.h"
-
-@implementation UiMenuDelegate 
-
-- (UiMenuDelegate*) init {
-    items = NULL;
-    itemlists = NULL;
-    return self;
-}
-
-- (void) menuNeedsUpdate:(NSMenu *) menu {
-    NSWindow *activeWindow = [NSApp keyWindow];
-    [(UiCocoaWindow*)activeWindow updateMenu: menu];
-}
-
-- (void) addItem:(NSMenuItem*) item var: (char*)name {
-    UiStateItem *i = malloc(sizeof(UiStateItem));
-    i->item = item;
-    i->var = name;
-    items = ucx_list_append(items, i);
-}
-
-- (void) addList:(UiList*) list menu:(NSMenu*)menu index: (int)i callback: (ui_callback)f data:(void*) data {
-    UiMenuItemList *itemList = malloc(sizeof(UiMenuItemList));
-    itemList->list = list;
-    itemList->menu = menu;
-    itemList->first = NULL;
-    itemList->index = i;
-    itemList->oldcount = 0;
-    itemList->callback = f;
-    itemList->data = data;
-    itemlists = ucx_list_append(itemlists, itemList);
-}
-
-- (UcxList*) items {
-    return items;
-}
-
-- (UcxList*) lists {
-    return itemlists;
-    
-}
-
-@end
-
-
-@implementation UiGroupMenuItem
-
-- (id)initWithTitle:(NSString*)title action:(SEL)action keyEquivalent:(NSString*)s {
-    [super initWithTitle:title action:action keyEquivalent:s];
-    groups = [[NSMutableArray alloc]initWithCapacity: 8];
-    return self;
-}
-
-- (void) addGroup:(int)group {
-    NSNumber *groupNumber = [NSNumber numberWithInteger:group];
-    [groups addObject:groupNumber];
-}
-
-- (void) checkGroups:(int*)g count:(int)n {
-    int c = [groups count];
-    
-    char *check = calloc(1, c);
-    for(int i=0;i<n;i++) {
-        for(int k=0;k<c;k++) {
-            NSNumber *groupNumber = [groups objectAtIndex:k];
-            if([groupNumber intValue] == g[i]) {
-                check[k] = 1;
-                break;
-            }
-        }
-    }
-    
-    for(int j=0;j<c;j++) {
-        if(check[j] == 0) {
-            [self setEnabled:NO];
-            return;
-        }
-    }
-    [self setEnabled:YES];
-}
-
-@end
-
-
-//static NSMenu *currentMenu = NULL;
-
-static UcxList *current;
-
-static int currentItemIndex = 0;
-static UiMenuDelegate *delegate;
-
-void ui_menu_init() {
-    delegate = [[UiMenuDelegate alloc]init];
-}
-
-UiMenuDelegate* ui_menu_delegate() {
-    return delegate;
-}
-
-
-void ui_menu(char *title) {
-    NSString *str = [[NSString alloc] initWithUTF8String:title];
-    
-    NSMenu *menu = [[NSMenu alloc] initWithTitle: str];
-    NSMenuItem *menuItem = [[NSApp mainMenu] addItemWithTitle:str
-                                                       action:nil keyEquivalent:@""];
-    [menu setDelegate: delegate];
-    [menu setAutoenablesItems:NO];
-    
-    [[NSApp mainMenu] setSubmenu:menu forItem:menuItem];
-    //currentMenu = menu;
-    currentItemIndex = 0;
-    
-    current = ucx_list_prepend(NULL, menu);
-}
-
-void ui_submenu(char *title) {
-    NSString *str = [[NSString alloc] initWithUTF8String:title];
-    NSMenu *currentMenu = current->data;
-    
-    NSMenu *menu = [[NSMenu alloc] initWithTitle: str];
-    NSMenuItem *menuItem = [currentMenu addItemWithTitle:str
-                                                       action:nil keyEquivalent:@""];
-    [menu setDelegate: delegate];
-    [menu setAutoenablesItems:NO];
-    
-    [currentMenu setSubmenu:menu forItem:menuItem];
-    //currentMenu = menu;
-    currentItemIndex = 0;
-    
-    current = ucx_list_prepend(current, menu);
-}
-
-void ui_submenu_end() {
-    if(ucx_list_size(current) < 2) {
-        return;
-    }
-    current = ucx_list_remove(current, current);
-}
-
-void ui_menuitem(char *label, ui_callback f, void *data) {
-    ui_menuitem_gr(label, f, data, -1);
-}
-
-void ui_menuitem_st(char *stockid, ui_callback f, void *data) {
-    ui_menuitem_stgr(stockid, f, data, -1);
-}
-
-void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) {
-    // create menu item
-    EventWrapper *event = [[EventWrapper alloc]initWithData:userdata callback:f];
-    NSString *title = [[NSString alloc] initWithUTF8String:label];
-    UiGroupMenuItem *item = [[UiGroupMenuItem alloc]initWithTitle:title action:@selector(handleEvent:) keyEquivalent:@""];
-    [item setTarget:event];
-    
-    // add groups
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        [item addGroup: group];
-    }
-    va_end(ap);
-    
-    NSMenu *currentMenu = current->data;
-    [currentMenu addItem:item];
-    
-    currentItemIndex++;
-}
-
-void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
-    // create menu item
-    EventWrapper *event = [[EventWrapper alloc]initWithData:userdata callback:f];
-    UiStockItem *si = ui_get_stock_item(stockid);
-    UiGroupMenuItem *item = [[UiGroupMenuItem alloc]initWithTitle:si->label
-                                action:@selector(handleEvent:)
-                                keyEquivalent:si->keyEquivalent];
-    [item setTarget:event];
-    
-    // add groups
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        [item addGroup: group];
-    }
-    va_end(ap);
-    
-    NSMenu *currentMenu = current->data;
-    [currentMenu addItem:item];
-    
-    currentItemIndex++;
-}
-
-void ui_checkitem(char *label, ui_callback f, void *data) {
-    EventWrapper *event = [[EventWrapper alloc]initWithData:data callback:f];
-    NSString *str = [[NSString alloc] initWithUTF8String:label];
-    
-    NSMenu *currentMenu = current->data;
-    NSMenuItem *item = [currentMenu addItemWithTitle:str
-                                              action:@selector(handleStateEvent:) keyEquivalent:@""];
-    [item setTarget:event];
-    
-    [delegate addItem: item var:NULL];
-    currentItemIndex++;
-}
-
-void ui_checkitem_nv(char *label, char *vname) {
-    EventWrapper *event = [[EventWrapper alloc]initWithData:NULL callback:NULL];
-    NSString *str = [[NSString alloc] initWithUTF8String:label];
-    
-    NSMenu *currentMenu = current->data;
-    NSMenuItem *item = [currentMenu addItemWithTitle:str
-                                              action:@selector(handleStateEvent:) keyEquivalent:@""];
-    [item setTarget:event];
-    
-    [delegate addItem: item var:vname];
-    currentItemIndex++;
-}
-
-void ui_menuseparator() {
-    NSMenu *currentMenu = current->data;
-    [currentMenu addItem: [NSMenuItem separatorItem]];
-    currentItemIndex++;
-}
-
-void ui_menuitem_list (UiList *items, ui_callback f, void *data) {
-    NSMenu *currentMenu = current->data;
-    [delegate addList:items menu:currentMenu index:currentItemIndex callback:f data:data];
-}
-
-
-
-int ui_menuitem_get(UiInteger *i) {
-    UiMenuItem *item = i->obj;
-    i->value = [item->item state];
-    return i->value;
-}
-
-void ui_menuitem_set(UiInteger *i, int value) {
-    UiMenuItem *item = i->obj;
-    [item->item setState: value];
-    i->value = value;
-    item->state = value;
-}
-
-
-int ui_update_item(UiCocoaWindow *window, void *data) {
-    UiMenuItem *item = data;
-    [item->item setState: item->state];
-    return 0;
-}
-
-int ui_update_item_list(UiCocoaWindow *window, void *data) {
-    UiMenuItemList *itemList = data;
-    UiList *list = itemList->list;
-    
-    for(int r=0;r<itemList->oldcount;r++) {
-        [itemList->menu removeItemAtIndex:itemList->index];
-    }
-    
-    char *str = ui_list_first(list);
-    int i = itemList->index;
-    [itemList->menu insertItem: [NSMenuItem separatorItem] atIndex: i];
-    i++;
-    while(str) {
-        EventWrapper *event = [[EventWrapper alloc]initWithData:itemList->data callback:itemList->callback];
-        [event setIntval: i - itemList->index - 1];
-        
-        NSString *title = [[NSString alloc] initWithUTF8String:str];
-        NSMenuItem *item = [[NSMenuItem alloc]initWithTitle:title action:@selector(handleEvent:) keyEquivalent:@""];
-        [item setTarget:event];
-        
-        [itemList->menu insertItem:item atIndex:i];
-        
-        str = ui_list_next(list);
-        i++;
-    }
-    
-    itemList->oldcount = i - itemList->index;
-    
-    return 0;
-}
--- a/ui/cocoa/objs.mk	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/objs.mk	Wed Dec 04 08:55:49 2024 +0100
@@ -30,16 +30,15 @@
 COCOA_OBJPRE = $(OBJ_DIR)/$(COCOA_SRC_DIR)
 
 COCOAOBJ = toolkit.o
+COCOAOBJ += AppDelegate.o
+COCOAOBJ += GridLayout.o
+COCOAOBJ += EventData.o
+COCOAOBJ += UiJob.o
+COCOAOBJ += MainWindow.o
+COCOAOBJ += WindowManager.o
 COCOAOBJ += window.o
-COCOAOBJ += menu.o
-COCOAOBJ += stock.o
-COCOAOBJ += toolbar.o
-COCOAOBJ += container.o
-COCOAOBJ += text.o
-COCOAOBJ += resource.o
-COCOAOBJ += tree.o
-COCOAOBJ += graphics.o
-
+COCOAOBJ += Container.o
+COCOAOBJ += button.o
 
 TOOLKITOBJS += $(COCOAOBJ:%=$(COCOA_OBJPRE)%)
 TOOLKITSOURCE += $(COCOAOBJ:%.o=cocoa/%.m)
--- a/ui/cocoa/resource.h	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "../ui/toolkit.h"
-#import "../ui/properties.h"
-
-
--- a/ui/cocoa/resource.m	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import <stdio.h>
-#import <stdlib.h>
-#import <string.h>
-
-#import "resource.h"
-#import "../common/properties.h"
-
-
-
-void ui_load_lang_def(char *locale, char *default_locale) {
-    NSString *localeString = nil;
-    char tmp[6];
-    if(!locale) {
-        NSString* lang = [[NSLocale currentLocale] localeIdentifier];
-        if(lang) {
-            localeString = lang;
-        } else {
-            [[NSString alloc]initWithUTF8String:default_locale];
-        }
-    } else {
-        localeString = [[NSString alloc]initWithUTF8String:locale];
-    }
-    
-    NSString *path = [[NSBundle mainBundle] pathForResource:localeString ofType:@"properties" inDirectory:@"locales"];
-    
-    const char *p = [path UTF8String];
-    
-    if(uic_load_language_file((char*)p)) {
-        if(default_locale) {
-            ui_load_lang_def(default_locale, NULL);
-        } else {
-            // cannot find any language file
-            fprintf(stderr, "Ui Error: Cannot load language.\n");
-            exit(-1);
-        }
-    }
-}
-
-void ui_locales_dir(char *path) {
-    // empty
-}
-
-void ui_pixmaps_dir(char *path) {
-    // empty
-}
\ No newline at end of file
--- a/ui/cocoa/stock.h	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "toolkit.h"
-#import "../ui/stock.h"
-#import <ucx/map.h>
-
-typedef struct UiStockItem {
-    NSString *label;
-    NSString *keyEquivalent;
-    NSImage  *image;
-} UiStockItem;
-
-void ui_stock_init();
-
-void ui_add_stock_item(char *stock_id, NSString *label, NSString *keyEquivalent, NSImage *image);
-
-UiStockItem* ui_get_stock_item(char *stock_id);
--- a/ui/cocoa/stock.m	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import <stdio.h>
-#import <stdlib.h>
-
-#import "stock.h"
-#import "../common/properties.h"
-
-static UcxMap *stock_items;
-
-void ui_stock_init() {
-    stock_items = ucx_map_new(64);
-    
-    ui_add_stock_item(UI_STOCK_NEW, @"New", @"n", nil);
-    ui_add_stock_item(UI_STOCK_OPEN, @"Open", @"o", nil);
-    ui_add_stock_item(UI_STOCK_SAVE, @"Save", @"s", nil);
-    ui_add_stock_item(UI_STOCK_SAVE_AS, @"Save as ...", @"", nil);
-    ui_add_stock_item(UI_STOCK_CLOSE, @"Close", @"w", nil);
-    ui_add_stock_item(UI_STOCK_UNDO, @"Undo", @"z", nil);
-    ui_add_stock_item(UI_STOCK_REDO, @"Redo", @"", nil);
-    ui_add_stock_item(UI_STOCK_CUT, @"Cut", @"x", nil);
-    ui_add_stock_item(UI_STOCK_COPY, @"Copy", @"c", nil);
-    ui_add_stock_item(UI_STOCK_PASTE, @"Paste", @"v", nil);
-    ui_add_stock_item(UI_STOCK_DELETE, @"Delete", @"", nil);
-    
-    ui_add_stock_item(UI_STOCK_GO_BACK, @"Back", @"", [NSImage imageNamed: NSImageNameGoLeftTemplate]);
-    ui_add_stock_item(UI_STOCK_GO_FORWARD, @"Forward", @"", [NSImage imageNamed: NSImageNameGoRightTemplate]);
-}
-
-void ui_add_stock_item(char *stock_id, NSString *label, NSString *keyEquivalent, NSImage *image) {
-    UiStockItem *i = malloc(sizeof(UiStockItem));
-    i->label = label;
-    i->keyEquivalent = keyEquivalent;
-    i->image = image;
-    
-    ucx_map_cstr_put(stock_items, stock_id, i);
-}
-
-UiStockItem* ui_get_stock_item(char *stock_id) {
-    UiStockItem *item = ucx_map_cstr_get(stock_items, stock_id);
-    if(item) {
-        char *label = uistr_n(stock_id);
-        if(label) {
-            NSString *str = [[NSString alloc]initWithUTF8String:label];
-            item->label = str;
-        }
-    }
-    return item;
-}
--- a/ui/cocoa/text.h	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "../ui/text.h"
-#import "toolkit.h"
-#import <ucx/list.h>
-
-@interface TextChangeMgr : NSObject<NSTextViewDelegate> {
-    UiContext *context;
-    UiText    *value;
-    int       last_length;
-}
-
-- (TextChangeMgr*)initWithValue:(UiText*)text context:(UiContext*)ctx;
-
-- (NSUndoManager*)undoManagerForTextView:(NSTextView*)textview;
-
-@end
-
-#define UI_TEXTBUF_INSERT 0
-#define UI_TEXTBUF_DELETE 1
-typedef struct UiTextBufOp {
-    int  type; // UI_TEXTBUF_INSERT, UI_TEXTBUF_DELETE
-    int  start;
-    int  end;
-    int  len;
-    char *text;
-} UiTextBufOp;
-
-
-
-char* ui_textarea_get(UiText *text);
-void ui_textarea_set(UiText *text, char *str);
-char* ui_textarea_getsubstr(UiText *text, int begin, int end);
-void ui_textarea_insert(UiText *text, int pos, char *str);
-int  ui_textarea_position(UiText *text);
-void ui_textarea_selection(UiText *text, int *begin, int *end);
-int ui_textarea_length(UiText *text);
--- a/ui/cocoa/text.m	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import <stdio.h>
-#import <stdlib.h>
-#import <string.h>
-
-#import "text.h"
-#import "container.h"
-
-@implementation TextChangeMgr
-
-- (TextChangeMgr*)initWithValue:(UiText*)text context:(UiContext*)ctx {
-    value = text;
-    context = ctx;
-    last_length = 0;
-    return self;
-}
-
-- (NSUndoManager*)undoManagerForTextView:(NSTextView*)textview {
-    return (NSUndoManager*)value->undomgr;
-}
-
-- (NSRange)textView:(NSTextView *)textview
-       willChangeSelectionFromCharacterRange:(NSRange)oldrange
-       toCharacterRange:(NSRange)newrange
-{
-    if(newrange.length != last_length) {
-        if(newrange.length == 0) {
-            ui_unset_group(context, UI_GROUP_SELECTION);
-        } else {
-            ui_set_group(context, UI_GROUP_SELECTION);
-        }
-    }
-    
-    last_length = newrange.length;
-    return newrange;
-}
-
-@end
-
-
-UIWIDGET ui_textarea(UiObject *obj, UiText *value) {
-    UiContainer *ct = uic_get_current_container(obj);
-    
-    NSRect frame = ct->getframe(ct);
-    
-    NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:frame];
-    [scrollview setHasVerticalScroller:YES];
-    //[scrollvew setHasHorizontalScroller:YES];
-    [scrollview setBorderType:NSNoBorder];
-    //[scrollview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
-    
-    //frame.size.width = frame.size.width - 15;
-    NSTextView *textview = [[NSTextView alloc]initWithFrame:frame];
-    [textview setAllowsUndo:TRUE];
-    [textview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
-    
-    [textview setFont:[NSFont fontWithName:@"Menlo" size:12]];
-    
-    [scrollview setDocumentView:textview];
-    
-    ct->add(ct, scrollview);
-    
-    // bind value
-    if(value) {
-        value->get = ui_textarea_get;
-        value->set = ui_textarea_set;
-        value->getsubstr = ui_textarea_getsubstr;
-        value->insert = ui_textarea_insert;
-        value->position = ui_textarea_position;
-        value->selection = ui_textarea_selection;
-        value->length = ui_textarea_length;
-        value->value = NULL;
-        value->obj = textview;
-        
-        TextChangeMgr *delegate = [[TextChangeMgr alloc]initWithValue:value context:obj->ctx];
-        [textview setDelegate:delegate];
-        
-        NSUndoManager *undomgr = [[NSUndoManager alloc]init];
-        value->undomgr = undomgr;
-    }
-    
-    return textview;
-}
-
-char* ui_textarea_get(UiText *text) {
-    if(text->value) {
-        free(text->value);
-    }
-    NSTextView *textview = (NSTextView*)text->obj;
-    NSString *str = [[textview textStorage]string];
-    size_t length = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-    const char *cstr = [str UTF8String];
-    char *value = malloc(length + 1);
-    memcpy(value, cstr, length);
-    value[length] = '\0';
-    text->value = value;
-    return value;
-}
-
-void ui_textarea_set(UiText *text, char *str) {
-    if(text->value) {
-        free(text->value);
-    }
-    NSTextView *textview = (NSTextView*)text->obj;
-    NSString *s = [[NSString alloc]initWithUTF8String:str];
-    NSAttributedString *as = [[NSAttributedString alloc]initWithString:s];
-    [[textview textStorage] setAttributedString:as];
-    text->value = NULL;
-}
-
-char* ui_textarea_getsubstr(UiText *text, int begin, int end) {
-    if(text->value) {
-        free(text->value);
-    }
-    NSTextView *textview = (NSTextView*)text->obj;
-    NSString *str = [[textview textStorage]string];
-    NSRange range;
-    range.location = begin;
-    range.length = end - begin;
-    
-    NSString *substr = [str substringWithRange:range];
-    size_t length = [substr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-    const char *cstr = [substr UTF8String];
-    char *value = malloc(length + 1);
-    memcpy(value, cstr, length);
-    value[length] = '\0';
-    text->value = value;
-    return value;
-}
-
-void ui_textarea_insert(UiText *text, int pos, char *str) {
-    if(text->value) {
-        free(text->value);
-    }
-    NSTextView *textview = (NSTextView*)text->obj;
-    NSString *s = [[NSString alloc]initWithUTF8String:str];
-    NSAttributedString *as = [[NSAttributedString alloc]initWithString:s];
-    [[textview textStorage] insertAttributedString:as atIndex: pos];
-    text->value = NULL;
-}
-
-int ui_textarea_position(UiText *text) {
-    return [[[(NSTextView*)text->obj selectedRanges] objectAtIndex:0] rangeValue].location;
-}
-
-void ui_textarea_selection(UiText *text, int *begin, int *end) {
-    NSRange range = [[[(NSTextView*)text->obj selectedRanges] objectAtIndex:0] rangeValue];
-    *begin = range.location;
-    *end = range.location + range.length;
-}
-
-int ui_textarea_length(UiText *text) {
-    return [[(NSTextView*)text->obj textStorage] length];
-}
-
-void ui_text_undo(UiText *text) {
-    [(NSUndoManager*)text->undomgr undo];
-}
-
-void ui_text_redo(UiText *text) {
-    [(NSUndoManager*)text->undomgr redo];
-}
-
--- a/ui/cocoa/toolbar.h	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "../ui/toolbar.h"
-#import "toolkit.h"
-#import <stdarg.h>
-
-
-@protocol UiToolItem
-- (NSToolbarItem *) createItem:(NSToolbar*)toolbar
-                    identifier:(NSString*)identifier
-                        object:(UiObject*)obj;
-
-- (void) addGroup:(int)group;
-
-- (UcxList*) groups;
-
-@end
-
-
-/*
- * UiToolbarStockItem
- *
- * creates a toolbar item from stock description
- */
-@interface UiToolbarStockItem : NSObject <UiToolItem> {
-    char           *name;
-    char           *stockid;
-    ui_callback    callback;
-    void           *userdata;
-    UcxList        *groups;
-    BOOL           isToggleButton;
-}
-
-- (UiToolbarStockItem*) initWithIdentifier:(char*)identifier
-                             stockID:(char*)sid
-                            callback:(ui_callback)f
-                            userdata:(void*)data;
-
-- (void) setIsToggleButton:(BOOL)t;
-
-
-@end
-
-/*
- * UiToolbarItem
- *
- * toolbar item with label and icon
- */
-@interface UiToolbarItem : NSObject <UiToolItem> {
-    char           *name;
-    char           *label;
-    // icon
-    ui_callback    callback;
-    void           *userdata;
-    UcxList        *groups;
-    BOOL           isToggleButton;
-}
-
-- (UiToolbarItem*) initWithIdentifier:(char*)identifier
-                                     label:(char*)lbl
-                                  callback:(ui_callback)f
-                                  userdata:(void*)data;
-
-- (void) setIsToggleButton:(BOOL)t;
-
-
-@end
-
-
-
-/*
- * UiToolbarDelegate
- */
-@interface UiToolbarDelegate : NSObject <NSToolbarDelegate> {
-    NSMutableArray      *allowedItems;
-    NSMutableArray      *defaultItems;
-    NSMutableDictionary *items;
-}
-
-- (UiToolbarDelegate*) init;
-
-- (void) addDefault:(NSString*)identifier;
-
-- (void) addItem: (NSString*) identifier
-            item: (NSObject<UiToolItem>*) item;
-
-@end
-
-
-/*
- * UiToolbar
- */
-@interface UiToolbar : NSToolbar {
-    UiObject *obj;
-}
-
-- (UiToolbar*) initWithObject:(UiObject*)object;
-
-- (UiObject*) object;
-
-@end
-
-void ui_toolbar_init();
-void ui_toolbar_stock_button(char *name, char *stockid, BOOL toggle, ui_callback f, void *udata, va_list ap);
-NSToolbar* ui_create_toolbar(UiObject *obj);
--- a/ui/cocoa/toolbar.m	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,358 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import <stdio.h>
-#import <stdlib.h>
-#import <string.h>
-#import <inttypes.h>
-#import <stdarg.h>
-
-#import "toolbar.h"
-#import "window.h"
-#import "stock.h"
-
-
-static UiToolbarDelegate* toolbar_delegate;
-
-/* ---------------------      UiToolbarStockItem     --------------------- */
-
-@implementation UiToolbarStockItem
-
-- (UiToolbarStockItem*) initWithIdentifier:(char*)identifier
-                                   stockID:(char*)sid
-                                  callback:(ui_callback)f
-                                  userdata:(void*)data
-{
-    name = identifier;
-    stockid = sid;
-    callback = f;
-    userdata = data;
-    groups = NULL;
-    isToggleButton = NO;
-    return self;
-}
-
-- (void) setIsToggleButton:(BOOL)t {
-    isToggleButton = t;
-}
-
-- (void) addGroup:(int)group {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
-}
-
-
-- (NSToolbarItem *) createItem:(NSToolbar*)toolbar
-                    identifier:(NSString*)identifier
-                        object:(UiObject*)obj
-{
-    UiStockItem *s = ui_get_stock_item(stockid);
-    if(s == nil) {
-        printf("cannot find stock item\n");
-        return nil;
-    }
-    
-    NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:
-                            identifier] autorelease];
-    //[item setLabel:[s label]];
-    //[item setPaletteLabel:[s label]];
-    [item setLabel:s->label];
-    [item setPaletteLabel:@"Operation"];
-    
-    // create button ...
-    NSRect frame = NSMakeRect(0, 0, 40, 22);
-    //NSSearchField *sf = [[NSSearchField alloc]initWithFrame:frame];
-    NSButton *button = [[NSButton alloc]initWithFrame:frame];
-    //[button setImage:[s buttonImage]];
-    //[button setImage:[NSImage imageNamed: NSImageNameAddTemplate]];
-    if(s->image) {
-        [button setImage:s->image];
-    } else {
-        [button setImage:[NSImage imageNamed: NSImageNameRemoveTemplate]];
-    }
-    [button setBezelStyle: NSTexturedRoundedBezelStyle];
-    
-    // event
-    EventWrapper *event = [[EventWrapper alloc]
-                           initWithData:userdata callback:callback];
-    if(isToggleButton) {
-        [button setButtonType: NSPushOnPushOffButton];
-        [button setAction:@selector(handleToggleEvent:)];
-    } else {
-        [button setAction:@selector(handleEvent:)];
-    }
-    [button setTarget:event];
-    
-    if(groups) {
-        uic_add_group_widget(obj->ctx, item, groups);
-    }
-    
-    [item setView:button];
-    return item;
-}
-
-- (UcxList*) groups {
-    return groups;
-}
-
-@end
-
-
-/* ---------------------      UiToolbarItem     --------------------- */
-
-@implementation UiToolbarItem
-
-- (UiToolbarItem*) initWithIdentifier:(char*)identifier
-                                     label:(char*)lbl
-                                  callback:(ui_callback)f
-                                  userdata:(void*)data
-{
-    name = identifier;
-    label = lbl;
-    callback = f;
-    userdata = data;
-    groups = NULL;
-    isToggleButton = NO;
-    return self;
-}
-
-- (void) setIsToggleButton:(BOOL)t {
-    isToggleButton = t;
-}
-
-- (void) addGroup:(int)group {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
-}
-
-
-- (NSToolbarItem *) createItem:(NSToolbar*)toolbar
-                    identifier:(NSString*)identifier
-                        object:(UiObject*)obj
-{
-    NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier:
-                            identifier] autorelease];
-    //[item setLabel:[s label]];
-    //[item setPaletteLabel:[s label]];
-    NSString *l = [[NSString alloc]initWithUTF8String:label];
-    [item setLabel:l];
-    [item setPaletteLabel:@"Operation"];
-    
-    // create button ...
-    NSRect frame = NSMakeRect(0, 0, 40, 22);
-    //NSSearchField *sf = [[NSSearchField alloc]initWithFrame:frame];
-    NSButton *button = [[NSButton alloc]initWithFrame:frame];
-    //[button setImage:[s buttonImage]];
-    //[button setImage:[NSImage imageNamed: NSImageNameAddTemplate]];
-    
-    // TODO: image
-    [button setImage:[NSImage imageNamed: NSImageNameRemoveTemplate]];
-    
-    [button setBezelStyle: NSTexturedRoundedBezelStyle];
-    
-    // event
-    EventWrapper *event = [[EventWrapper alloc]
-                           initWithData:userdata callback:callback];
-    if(isToggleButton) {
-        [button setButtonType: NSPushOnPushOffButton];
-        [button setAction:@selector(handleToggleEvent:)];
-    } else {
-        [button setAction:@selector(handleEvent:)];
-    }
-    [button setTarget:event];
-    
-    if(groups) {
-        uic_add_group_widget(obj->ctx, item, groups);
-    }
-    
-    [item setView:button];
-    return item;
-}
-
-- (UcxList*) groups {
-    return groups;
-}
-
-@end
-
-
-/* ---------------------      UiToolbarDelegate      --------------------- */
-
-@implementation UiToolbarDelegate
-
-- (UiToolbarDelegate*) init {
-    allowedItems = [[NSMutableArray alloc]initWithCapacity: 16];
-    defaultItems = [[NSMutableArray alloc]initWithCapacity: 16];
-    items = [[NSMutableDictionary alloc] init];
-    return self;
-}
-
-- (void) addDefault:(NSString*)identifier {
-    [defaultItems addObject: identifier];
-}
-
-- (void) addItem: (NSString*) identifier
-            item: (NSObject<UiToolItem>*) item
-{
-    [allowedItems addObject: identifier];
-    [items setObject: item forKey:identifier];
-}
-
-/*
-- (void) addStockItem:(char*)name
-              stockID:(char*)sid
-             callback:(ui_callback)f
-                 data:(void*)userdata
-{
-    UiToolbarStockItem *item = [[UiToolbarStockItem alloc]initWithData:name
-                                                               stockID:sid callback:f data:userdata];
-    
-    NSString *s = [[NSString alloc]initWithUTF8String:name];
-    [allowedItems addObject: s];
-    [items setObject: item forKey:s];
-}
-*/
-
-// implementation of NSToolbarDelegate methods
-- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar {
-    NSMutableArray *i = [[NSMutableArray alloc]
-                         initWithCapacity:[allowedItems count] + 3];
-    [i addObject: NSToolbarFlexibleSpaceItemIdentifier];
-    [i addObject: NSToolbarSpaceItemIdentifier];
-    [i addObject: NSToolbarSeparatorItemIdentifier];
-    for(id item in allowedItems) {
-        [i addObject: item];
-    }
-    
-    return i;
-}
-
-- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar {
-    return defaultItems;
-}
-
-- (NSToolbarItem *) toolbar:(NSToolbar*)toolbar
-         itemForItemIdentifier:(NSString*)identifier
-     willBeInsertedIntoToolbar:(BOOL)flag
-{
-    Protocol *item = @protocol(UiToolItem);
-    item = [items objectForKey: identifier];
-    
-    // get UiObject from toolbar
-    UiObject *obj = [(UiToolbar*)toolbar object];
-    
-    // create new NSToolbarItem
-    return [item createItem:toolbar identifier:identifier object:obj];
-}
-
-@end
-
-
-@implementation UiToolbar
-
-- (UiToolbar*) initWithObject:(UiObject*)object {
-    [self initWithIdentifier: @"MainToolbar"];
-    obj = object;
-    return self;
-}
-
-- (UiObject*) object {
-    return obj;
-}
-
-@end
-
-
-/* ---------------------          functions          --------------------- */
-
-void ui_toolbar_init() {
-    toolbar_delegate = [[UiToolbarDelegate alloc]init];
-}
-
-void ui_toolitem(char *name, char *label, ui_callback f, void *udata) {
-    UiToolbarItem *item = [[UiToolbarItem alloc]
-                                initWithIdentifier: name
-                                label: label
-                                callback: f
-                                userdata: udata];
-    
-    NSString *identifier = [[NSString alloc]initWithUTF8String:name];
-    [toolbar_delegate addItem: identifier item: item];
-}
-
-void ui_toolitem_st(char *name, char *stockid, ui_callback f, void *udata) {
-    ui_toolitem_stgr(name, stockid, f, udata, -1);
-}
-
-void ui_toolitem_stgr(char *name, char *stockid, ui_callback f, void *udata, ...) {
-    va_list ap;
-    va_start(ap, udata);
-    ui_toolbar_stock_button(name, stockid, NO, f, udata, ap);
-    va_end(ap);
-}
-
-void ui_toolitem_toggle_st(char *name, char *stockid, ui_callback f, void *udata) {
-    ui_toolitem_toggle_stgr(name, stockid, f, udata, -1);
-}
-
-void ui_toolitem_toggle_stgr(char *name, char *stockid, ui_callback f, void *udata, ...) {
-    va_list ap;
-    va_start(ap, udata);
-    ui_toolbar_stock_button(name, stockid, YES, f, udata, ap);
-    va_end(ap);
-}
-
-
-void ui_toolbar_stock_button(char *name, char *stockid, BOOL toggle, ui_callback f, void *udata, va_list ap) {
-    UiToolbarStockItem *item = [[UiToolbarStockItem alloc]
-                                initWithIdentifier: name
-                                stockID: stockid
-                                callback: f
-                                userdata: udata];
-    [item setIsToggleButton: toggle];
-    NSString *identifier = [[NSString alloc]initWithUTF8String:name];
-    [toolbar_delegate addItem: identifier item: item];
-    
-    // add groups
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        [item addGroup: group];
-    }
-}
-
-
-void ui_toolbar_add_default(char *name) {
-    NSString *identifier = [[NSString alloc]initWithUTF8String:name];
-    [toolbar_delegate addDefault: identifier];
-}
-
-NSToolbar* ui_create_toolbar(UiObject *obj) {
-    UiToolbar *toolbar = [[UiToolbar alloc] initWithObject:obj];
-    [toolbar setDelegate: toolbar_delegate];
-    [toolbar setAllowsUserCustomization: true];
-    return toolbar;
-}
-
--- a/ui/cocoa/toolkit.h	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/toolkit.h	Wed Dec 04 08:55:49 2024 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -31,58 +31,7 @@
 #include "../common/context.h"
 #include "../common/object.h"
 
-
-@interface UiApplicationDelegate : NSObject<NSApplicationDelegate> {
-    
-}
-
-- (void)applicationWillTerminate:(NSNotification*)notification;
-
-- (BOOL)applicationShouldHandleReopen:(NSApplication *)app hasVisibleWindows:(BOOL)visible;
-
-- (BOOL)application:(NSApplication *)application openFile:(NSString *)filename;
-
-@end
-
-@interface EventWrapper : NSObject {
-    void         *data;
-    ui_callback  callback;
-    int          value;
-}
-
-- (EventWrapper*) initWithData: (void*)data callback:(ui_callback) f;
-
-- (void*) data;
-- (void) setData:(void*)d;
-- (ui_callback) callback;
-- (void) setCallback: (ui_callback)f;
-- (int) intval;
-- (void) setIntval:(int)i;
+void ui_cocoa_onstartup(void);
+void ui_cocoa_onopen(const char *file);
+void ui_cocoa_onexit(void);
 
-- (BOOL)handleEvent:(id)sender;
-- (BOOL)handleStateEvent:(id)sender;
-- (BOOL)handleToggleEvent:(id)sender;
-
-@end
-
-@interface UiThread : NSObject {
-    UiObject      *obj;
-    ui_threadfunc job_func;
-    void          *job_data;
-    ui_callback   finish_callback;
-    void          *finish_data;
-}
-
-- (id) initWithObject:(UiObject*)object;
-- (void) setJobFunction:(ui_threadfunc)func;
-- (void) setJobData:(void*)data;
-- (void) setFinishCallback:(ui_callback)callback;
-- (void) setFinishData:(void*)data;
-
-- (void) start;
-- (void) runJob:(id)n;
-- (void) finish:(id)n;
-
-@end
-
-
--- a/ui/cocoa/toolkit.m	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/toolkit.m	Wed Dec 04 08:55:49 2024 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -26,321 +26,126 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <stdio.h>
-#import <stdlib.h>
-#import <sys/stat.h>
-#import <sys/types.h>
-#import <errno.h>
-
-#import "../common/context.h"
-#import "../common/document.h"
-#import "../common/properties.h"
+#import "toolkit.h"
 
-#import "toolkit.h"
-#import "window.h"
-#import "menu.h"
-#import "toolbar.h"
-#import "stock.h"
+#include "../common/document.h"
+#include "../common/properties.h"
+#include "../common/menu.h"
+#include "../common/toolbar.h"
+#include "../common/threadpool.h"
 
-NSAutoreleasePool *pool;
+#import "AppDelegate.h"
 
-static char *application_name;
+static const char *application_name;
+
+static int app_argc;
+static const char **app_argv;
 
-static ui_callback   appclose_fnc;
-static void          *appclose_udata;
+static ui_callback   startup_func;
+static void          *startup_data;
+static ui_callback   open_func;
+void                 *open_data;
+static ui_callback   exit_func;
+void                 *exit_data;
 
-static ui_callback   openfile_fnc;
-static void          *openfile_udata;
+/* ------------------- App Init / Event Loop functions ------------------- */
 
-void ui_init(char *appname, int argc, char **argv) {
-    pool = [[NSAutoreleasePool alloc] init];
-    [NSApplication sharedApplication];
-    [NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
+void ui_init(const char *appname, int argc, char **argv) {
+    application_name = appname;
+    app_argc = argc;
+    app_argv = (const char**)argv;
     
-    UiApplicationDelegate *delegate = [[UiApplicationDelegate alloc]init];
-    [NSApp setDelegate: delegate];
-    
-    
+    uic_init_global_context();
+
     uic_docmgr_init();
-    ui_menu_init();
-    ui_toolbar_init();
-    ui_stock_init();
-    
+    uic_menu_init();
+    uic_toolbar_init();
+
     uic_load_app_properties();
+
+    [NSApplication sharedApplication];
+    //[NSBundle loadNibNamed:@"MainMenu" owner:NSApp ];
+    //[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp topLevelObjects:&topLevelObjects];
 }
 
-char* ui_appname() {
+const char* ui_appname() {
     return application_name;
 }
 
-void ui_exitfunc(ui_callback f, void *userdata) {
-    appclose_fnc = f;
-    appclose_udata = userdata;
-}
-
-void ui_openfilefunc(ui_callback f, void *userdata) {
-    openfile_fnc = f;
-    openfile_udata = userdata;
+void ui_onstartup(ui_callback f, void *userdata) {
+    startup_func = f;
+    startup_data = userdata;
 }
 
-void ui_show(UiObject *obj) {
-    uic_check_group_widgets(obj->ctx);
-    if([obj->widget class] == [UiCocoaWindow class]) {
-        UiCocoaWindow *window = (UiCocoaWindow*)obj->widget;
-        [window makeKeyAndOrderFront:nil];
-    } else {
-        printf("Error: ui_show: Object is not a Window!\n");
-    }
-}
-
-void ui_set_show_all(UIWIDGET widget, int value) {
-    // TODO
-}
-
-void ui_set_visible(UIWIDGET widget, int visible) {
-    // TODO
-}
-
-void ui_set_enabled(UIWIDGET widget, int enabled) {
-    [(id)widget setEnabled: enabled];
+void ui_onopen(ui_callback f, void *userdata) {
+    open_func = f;
+    open_data = userdata;
 }
 
-
-
-void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd) {
-    UiThread *thread = [[UiThread alloc]initWithObject:obj];
-    [thread setJobFunction:tf];
-    [thread setJobData:td];
-    [thread setFinishCallback:f];
-    [thread setFinishData:fd];
-    [thread start];
-}
-
-void ui_main() {
-    [NSApp run];
-    [pool release];
+void ui_onexit(ui_callback f, void *userdata) {
+    exit_func = f;
+    exit_data = userdata;
 }
 
-
-void ui_clipboard_set(char *str) {
-    NSString *string = [[NSString alloc] initWithUTF8String:str];
-    NSPasteboard * pasteBoard = [NSPasteboard generalPasteboard];
-    [pasteBoard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
-    [pasteBoard setString:string forType:NSStringPboardType];
-}
-
-char* ui_clipboard_get() {
-    NSPasteboard * pasteBoard = [NSPasteboard generalPasteboard];
-    NSArray *classes = [[NSArray alloc] initWithObjects:[NSString class], nil];
-    NSDictionary *options = [NSDictionary dictionary];
-    NSArray *data = [pasteBoard readObjectsForClasses:classes options:options];
-    
-    if(data != nil) {
-        NSString *str = [data componentsJoinedByString: @""];
-        
-        // copy C string
-        size_t length = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
-        const char *cstr = [str UTF8String];
-        char *value = malloc(length + 1);
-        memcpy(value, cstr, length);
-        value[length] = '\0';
-        
-        return value;
-    } else {
-        return NULL;
+void ui_cocoa_onstartup(void) {
+    UiEvent e;
+    e.obj = NULL;
+    e.window = NULL;
+    e.document = NULL;
+    e.eventdata = NULL;
+    e.intval = 0;
+    if(startup_func) {
+        startup_func(&e, startup_data);
     }
 }
 
-
-@implementation UiApplicationDelegate
-
-- (void)applicationWillTerminate:(NSNotification*)notification {
-    printf("terminate\n");
-}
-
-- (BOOL)applicationShouldHandleReopen:(NSApplication *)app hasVisibleWindows:(BOOL)visible; {
-    if(!visible) {
-        printf("reopen\n");
-    }
-    return NO;
-}
-
-- (BOOL)application:(NSApplication*)application openFile:(NSString*)filename {
-    if(openfile_fnc) {
-        UiEvent event;
-        event.obj = NULL;
-        event.document = NULL;
-        event.window = NULL;
-        event.eventdata = (void*)[filename UTF8String];
-        event.intval = 0;
-        openfile_fnc(&event, openfile_udata);
+void ui_cocoa_onopen(const char *file) {
+    UiEvent e;
+    e.obj = NULL;
+    e.window = NULL;
+    e.document = NULL;
+    e.eventdata = NULL;
+    e.intval = 0;
+    if(open_func) {
+        open_func(&e, open_data);
     }
-    
-    return NO;
-}
-
-@end
-
-
-@implementation EventWrapper
-
-- (EventWrapper*) initWithData: (void*)d callback:(ui_callback) f {
-    data = d;
-    callback = f;
-    value = 0;
-    return self;
-}
-
-
-- (void*) data {
-    return data;
-}
-
-- (void) setData:(void*)d {
-    data = d;
-}
-
-
-- (ui_callback) callback {
-    return callback;
-}
-
-- (void) setCallback: (ui_callback)f {
-    callback = f;
-}
-
-- (int) intval {
-    return value;
-}
-
-- (void) setIntval:(int)i {
-    value = i;
-}
-
-
-- (BOOL)handleEvent:(id)sender {
-    NSWindow *activeWindow = [NSApp keyWindow];
-    
-    UiEvent event;
-    event.eventdata = NULL;
-    if([activeWindow class] == [UiCocoaWindow class]) {
-        event.obj = [(UiCocoaWindow*)activeWindow object];
-        event.window = event.obj->window;
-        event.document = event.obj->ctx->document;
-        event.intval = value;
-    }
-    if(callback) {
-        callback(&event, data);
-    }
-    
-    return true;
 }
 
-- (BOOL)handleStateEvent:(id)sender {
-    NSWindow *activeWindow = [NSApp keyWindow];
-    int state = [sender state] ? NSOffState : NSOnState;
-    
-    UiEvent event;
-    event.intval = state;
-    event.eventdata = NULL;
-    if([activeWindow class] == [UiCocoaWindow class]) {
-        event.obj = [(UiCocoaWindow*)activeWindow object];
-        event.window = event.obj->window;
-        event.document = event.obj->ctx->document;
-        // if the sender is a menu item, we have to save the state for this
-        // window
-        UiMenuItem *wmi = [(UiCocoaWindow*)activeWindow getMenuItem: sender];
-        if(wmi) {
-            // update state in window data
-            wmi->state = state;
-        }
-    } else {
-        event.window = NULL;
-        event.document = NULL;
-    }
-    if(callback) {
-        callback(&event, data);
-    }
-    [sender setState: state];
-    
-    return true;
-}
-
-- (BOOL)handleToggleEvent:(id)sender {
-    NSWindow *activeWindow = [NSApp keyWindow];
-    
-    UiEvent event;
-    event.intval = [sender state];
-    event.eventdata = NULL;
-    if([activeWindow class] == [UiCocoaWindow class]) {
-        event.obj = [(UiCocoaWindow*)activeWindow object];
-        event.window = event.obj->window;
-        event.document = event.obj->ctx->document;
-    } else {
-        event.window = NULL;
-        event.document = NULL;
-    }
-    if(callback) {
-        callback(&event, data);
-    }
-    
-    return true;
-}
-
-@end
-
-@implementation UiThread
-
-- (id) initWithObject:(UiObject*)object {
-    obj = object;
-    job_func = NULL;
-    job_data = NULL;
-    finish_callback = NULL;
-    finish_data = NULL;
-    return self;
-}
-
-- (void) setJobFunction:(ui_threadfunc)func {
-    job_func = func;
-}
-
-- (void) setJobData:(void*)data {
-    job_data = data;
-}
-
-- (void) setFinishCallback:(ui_callback)callback {
-    finish_callback = callback;
-}
-
-- (void) setFinishData:(void*)data {
-    finish_data = data;
-}
-
-- (void) start {
-    [NSThread detachNewThreadSelector:@selector(runJob:)
-                             toTarget:self
-                           withObject:nil];
-}
-
-- (void) runJob:(id)n {
-    int result = job_func(job_data);
-    if(!result) {
-        [self performSelectorOnMainThread:@selector(finish:)
-                               withObject:nil
-                            waitUntilDone:NO];
+void ui_cocoa_onexit(void) {
+    UiEvent e;
+    e.obj = NULL;
+    e.window = NULL;
+    e.document = NULL;
+    e.eventdata = NULL;
+    e.intval = 0;
+    if(exit_func) {
+        exit_func(&e, exit_data);
     }
 }
 
-- (void) finish:(id)n {
-    UiEvent event;
-    event.obj = obj;
-    event.window = obj->window;
-    event.document = obj->ctx->document;
-    event.eventdata = NULL;
-    event.intval = 0;
-    finish_callback(&event, finish_data);
+void ui_main(void) {
+    NSApplicationMain(app_argc, app_argv);
+}
+
+/* ------------------- Window Visibility functions ------------------- */
+
+void ui_show(UiObject *obj) {
+    if(obj->wobj) {
+        NSWindow *window = (__bridge NSWindow*)obj->wobj;
+        [window makeKeyAndOrderFront:nil];
+    }
 }
 
-@end
+void ui_close(UiObject *obj) {
+
+}
+
+/* ------------------- Job Control / Threadpool functions ------------------- */
 
+void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd) {
 
+}
+
+void ui_call_mainthread(ui_threadfunc tf, void* td) {
+
+}
--- a/ui/cocoa/tree.h	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- 
- #import "../ui/tree.h"
- #import "toolkit.h"
- 
- 
-@interface UiTableDataSource : NSObject<NSTableViewDataSource, NSTableViewDelegate> {
-    UiList          *data;
-    UiModelInfo     *info;
-    UiListSelection *lastSelection;
-}
-
-- (id)initWithData:(UiList*)list modelInfo:(UiModelInfo*)modelinfo;
-
-- (void)handleDoubleAction:(id)sender;
-
-@end
-
-
-char* ui_type_to_string(UiModelType type, void *data, BOOL *free);
-
--- a/ui/cocoa/tree.m	Sat Nov 30 20:33:16 2024 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *   1. Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *
- *   2. Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- 
-#import <stdio.h>
-#import <stdlib.h>
- 
-#import "tree.h"
-#import "container.h"
-#import "window.h"
-#import "../common/context.h"
-#import <ucx/utils.h>
-
-@implementation UiTableDataSource
-
-- (id)initWithData:(UiList*)list modelInfo:(UiModelInfo*)modelinfo {
-    data = list;
-    info = modelinfo;
-    lastSelection = NULL;
-    return self;
-}
-
-- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableview {
-    return data->count(data);
-}
-
-- (id)tableView:                  (NSTableView*)tableview
-        objectValueForTableColumn:(NSTableColumn*)column
-                              row:(NSInteger)row
-{
-    int column_index = [[column identifier]intValue];
-    
-    void *row_data = data->get(data, row);
-    void *cell_data = info->getvalue(row_data, column_index);
-    
-    BOOL f = false;
-    char *str = ui_type_to_string(info->types[column_index], cell_data, &f);
-    NSString *s = [[NSString alloc]initWithUTF8String:str];
-    return s;
-}
-
-- (void)tableView:(NSTableView *)tableview
-        setObjectValue:(id)object
-        forTableColumn:(NSTableColumn *)column
-                   row:(NSInteger)row
-{
-    int column_index = [[column identifier]intValue];
-    
-    // TODO
-}
-
-- (void)tableViewSelectionDidChange:(NSNotification *)notification {
-    NSTableView *tableview = (NSTableView*)notification.object;
-    
-    // create selection object
-    UiListSelection *selection = malloc(sizeof(UiListSelection));
-    selection->count = [tableview numberOfSelectedRows];
-    
-    selection->rows = calloc(selection->count, sizeof(int));
-    NSIndexSet *indices = [tableview selectedRowIndexes];
-    NSUInteger index = [indices firstIndex];
-    int i=0;
-    while (index!=NSNotFound) {
-        selection->rows[i] = index;
-        index = [indices indexGreaterThanIndex:index];
-        i++;
-    }
-    
-    // create event object
-    UiEvent event;
-    NSWindow *activeWindow = [NSApp keyWindow];
-    if([activeWindow class] == [UiCocoaWindow class]) {
-        event.obj = [(UiCocoaWindow*)activeWindow object];
-        event.window = event.obj->window;
-        event.document = event.obj->ctx->document;
-    } else {
-        event.window = NULL;
-        event.document = NULL;
-    }
-    event.eventdata = selection;
-    event.intval = selection->count == 0 ? -1 : selection->rows[0];
-    
-    // callback
-    info->selection(&event, info->userdata);
-    
-    // cleanup
-    if(lastSelection) {
-        free(lastSelection->rows);
-        free(lastSelection);
-    }
-    lastSelection = selection;
-}
-
-- (void)handleDoubleAction:(id)sender {
-    // create event object
-    UiEvent event;
-    NSWindow *activeWindow = [NSApp keyWindow];
-    if([activeWindow class] == [UiCocoaWindow class]) {
-        event.obj = [(UiCocoaWindow*)activeWindow object];
-        event.window = event.obj->window;
-        event.document = event.obj->ctx->document;
-    } else {
-        event.window = NULL;
-        event.document = NULL;
-    }
-    event.eventdata = lastSelection;
-    event.intval = lastSelection->count == 0 ? -1 : lastSelection->rows[0];
-    
-    info->activate(&event, info->userdata);
-}
-
-- (BOOL)tableView:(NSTableView *)tableview isGroupRow:(NSInteger)row {
-    return NO;
-}
-
-@end
-
-
-UIWIDGET ui_table(UiObject *obj, UiList *model, UiModelInfo *modelinfo) {
-    UiContainer *ct = uic_get_current_container(obj);
-    NSRect frame = ct->getframe(ct);
-    
-    NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:frame];
-    [scrollview setHasVerticalScroller:YES];
-    //[scrollvew setHasHorizontalScroller:YES];
-    [scrollview setBorderType:NSNoBorder];
-    //[scrollview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
-    
-    NSTableView *tableview = [[NSTableView alloc]initWithFrame:frame];
-    [scrollview setDocumentView:tableview];
-    [tableview setAllowsMultipleSelection: YES];
-    //[tableview setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList];
-    
-    // add columns
-    for(int i=0;i<modelinfo->columns;i++) {
-        NSString *cid = [[NSString alloc]initWithFormat: @"%d", i];
-        NSTableColumn *column = [[NSTableColumn alloc]initWithIdentifier:cid];
-        
-        NSString *title = [[NSString alloc]initWithUTF8String: modelinfo->titles[i]];
-        [[column headerCell] setStringValue:title];
-        
-        [tableview addTableColumn:column];
-    }
-    
-    UiTableDataSource *source = [[UiTableDataSource alloc]initWithData:model modelInfo:modelinfo];
-    [tableview setDataSource:source];
-    [tableview setDelegate:source];
-
-    [tableview setDoubleAction:@selector(handleDoubleAction:)];
-    [tableview setTarget:source];
-    
-    
-    ct->add(ct, scrollview);
-    return scrollview;
-}
-
-
-UIWIDGET ui_listview_var(UiObject *obj, UiListPtr *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) {
-    UiContainer *ct = uic_get_current_container(obj);
-    NSRect frame = ct->getframe(ct);
-    
-    NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:frame];
-    [scrollview setHasVerticalScroller:YES];
-    
-    [scrollview setBorderType:NSNoBorder];
-    
-    NSTableView *tableview = [[NSTableView alloc]initWithFrame:frame];
-    [scrollview setDocumentView:tableview];
-    [tableview setAllowsMultipleSelection: NO];
-    
-    // add single column
-    NSTableColumn *column = [[NSTableColumn alloc]initWithIdentifier:@"c"];
-    [tableview addTableColumn:column];
-    
-    // create model info
-    UiModelInfo *modelinfo = ui_model_info(obj->ctx, UI_STRING, -1);
-    
-    // add source
-    UiTableDataSource *source = [[UiTableDataSource alloc]initWithData:list->list modelInfo:modelinfo];
-    
-    [tableview setDataSource:source];
-    [tableview setDelegate:source];
-
-    [tableview setDoubleAction:@selector(handleDoubleAction:)];
-    [tableview setTarget:source];
-    
-    ct->add(ct, scrollview);
-    return scrollview;
-}
-
-UIWIDGET ui_listview(UiObject *obj, UiList *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) {
-    UiListPtr *listptr = ucx_mempool_malloc(obj->ctx->mempool, sizeof(UiListPtr));
-    listptr->list = list;
-    return ui_listview_var(obj, listptr, getvalue, f, udata);
-}
-
-UIWIDGET ui_listview_nv(UiObject *obj, char *varname, ui_model_getvalue_f getvalue, ui_callback f, void *udata) {
-    UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_LIST);
-    if(var) {
-        UiListVar *value = var->value;
-        return ui_listview_var(obj, value->listptr, getvalue, f, udata);
-    } else {
-        // TODO: error
-    }
-    return NULL;
-}
-
-
-// TODO: motif code duplicate
-char* ui_type_to_string(UiModelType type, void *data, BOOL *free) {
-    switch(type) {
-        case UI_STRING: *free = FALSE; return data;
-        case UI_INTEGER: {
-            *free = TRUE;
-            int *val = data;
-            sstr_t str = ucx_asprintf(ucx_default_allocator(), "%d", *val);
-            return str.ptr;
-        }
-    }
-    *free = FALSE;
-    return NULL;
-}
--- a/ui/cocoa/window.h	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/window.h	Wed Dec 04 08:55:49 2024 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -26,27 +26,4 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import <Cocoa/Cocoa.h>
-#import "../ui/window.h"
-#import <ucx/list.h>
-#import <ucx/map.h>
-
-#import "menu.h"
-
-
-
-@interface UiCocoaWindow : NSWindow {
-    UiObject *uiobj;
-    UcxMap   *menus; // key: NSMenu value: UcxList of UiMenuItem
-    UcxMap   *items; // key: NSMenuItem value: UiMenuItem
-}
-
-- (UiCocoaWindow*) init: (NSRect)frame object: (UiObject*)obj;
-- (UiObject*) object;
-- (void) setObject:(UiObject*)obj;
-- (void) setMenuItems:(UcxList*)menuItems;
-- (void) setMenuItemLists:(UcxList*)itemLists;
-- (UiMenuItem*) getMenuItem:(NSMenuItem*)item;
-- (void) updateMenu:(NSMenu*)menu;
-
-@end
+#import "toolkit.h"
\ No newline at end of file
--- a/ui/cocoa/window.m	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/cocoa/window.m	Wed Dec 04 08:55:49 2024 +0100
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2012 Olaf Wintermann. All rights reserved.
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -26,195 +26,43 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#import "window.h"
 
-#import "window.h"
-#import "menu.h"
-#import "toolbar.h"
-#import "container.h"
-#import <ucx/mempool.h>
-#import "../common/context.h"
-
-static int window_default_width = 600;
-static int window_default_height = 500;
-
-@implementation UiCocoaWindow
+#import "MainWindow.h"
+#import "WindowManager.h"
 
-- (UiCocoaWindow*) init: (NSRect)frame object: (UiObject*)obj {
-    self = [self initWithContentRect:frame
-                           styleMask:NSTitledWindowMask |
-                                     NSResizableWindowMask |
-                                     NSClosableWindowMask |
-                                     NSMiniaturizableWindowMask
-                             backing:NSBackingStoreBuffered
-                               defer:false];
-    
-    uiobj = obj;
-    UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
-    menus = ucx_map_new_a(allocator, 8);
-    items = ucx_map_new_a(allocator, 64);
-    
-    return self;
-}
+#include "../ui/window.h"
+#include "../ui/properties.h"
+#include "../common/context.h"
+#include "../common/menu.h"
+#include "../common/toolbar.h"
 
-- (UiObject*) object {
-    return uiobj;
-}
+#include <cx/mempool.h>
 
-- (void)  setObject:(UiObject*)obj {
-    uiobj = obj;
-}
-
-- (void) setMenuItems:(UcxList*)menuItems {
-    UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
+static UiObject* create_window(const char *title, BOOL simple) {
+    CxMempool *mp = cxBasicMempoolCreate(256);
+    UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject));
+    obj->ref = 0;
     
-    UCX_FOREACH(elm, menuItems) {
-        UiStateItem *item = elm->data;
-        NSMenu *menu = [item->item menu];
-        
-        // create UiMenuItem which represents an NSMenuItem for a Window
-        UiMenuItem *windowItem = ucx_mempool_malloc(uiobj->ctx->mempool, sizeof(UiMenuItem));
-        windowItem->item = item->item;
-        windowItem->state = 0;
-        if(item->var) {
-            // bind value
-            UiVar *var = uic_connect_var(uiobj->ctx, item->var, UI_VAR_INTEGER);
-            if(var) {
-                UiInteger *value = var->value;
-                value->obj = windowItem;
-                value->get = ui_menuitem_get;
-                value->set = ui_menuitem_set;
-                value = 0;
-            } else {
-                // TODO: error
-            }
-        }
-        
-        // add item
-        UiAbstractMenuItem *abstractItem = malloc(sizeof(UiAbstractMenuItem));
-        abstractItem->update = ui_update_item;
-        abstractItem->item_data = windowItem;
-        UcxList *itemList = ucx_map_get(menus, ucx_key(&menu, sizeof(void*)));
-        itemList = ucx_list_append_a(allocator, itemList, abstractItem);
-        ucx_map_put(menus, ucx_key(&menu, sizeof(void*)), itemList);
-        
-        ucx_map_put(items, ucx_key(&windowItem->item, sizeof(void*)), windowItem);
-    }
-}
-
-- (void) setMenuItemLists:(UcxList*)itemLists {
-    UcxAllocator *allocator = uiobj->ctx->mempool->allocator;
-    
-    UCX_FOREACH(elm, itemLists) {
-        UiMenuItemList *list = elm->data;
-        
-        UiAbstractMenuItem *abstractItem = malloc(sizeof(UiAbstractMenuItem));
-        abstractItem->update = ui_update_item_list;
-        abstractItem->item_data = list;
-        
-        UcxList *itemList = ucx_map_get(menus, ucx_key(&list->menu, sizeof(void*)));
-        itemList = ucx_list_append_a(allocator, itemList, abstractItem);
-        ucx_map_put(menus, ucx_key(&list->menu, sizeof(void*)), itemList);
-        
-    }
-}
-
-- (UiMenuItem*) getMenuItem:(NSMenuItem*)item {
-    return ucx_map_get(items, ucx_key(&item, sizeof(void*)));
-}
-
-- (void) updateMenu:(NSMenu*)menu {
-    UcxList *itemList = ucx_map_get(menus, ucx_key(&menu, sizeof(void*)));
-    UCX_FOREACH(elm, itemList) {
-        UiAbstractMenuItem *item = elm->data;
-        item->update(self, item->item_data);
-    }
-    
-    // update group items
-    // TODO: use only one loop for all items
-    int ngroups = 0;
-    int *groups = ui_active_groups(uiobj->ctx, &ngroups);
-    
-    NSArray *groupItems = [menu itemArray];
-    int count = [groupItems count];
-    for(int i=0;i<count;i++) {
-        id item = [groupItems objectAtIndex:i];
-        if([item class] == [UiGroupMenuItem class]) {
-            [item checkGroups: groups count:ngroups];
-        }
-    }
-    free(groups);
-}
-
-@end
-
-
-/* ------------------------------ public API ------------------------------ */
-
-UiObject* ui_window(char *title, void *window_data) {
-    UcxMempool *mp = ucx_mempool_new(256);
-    UiObject *obj = ucx_mempool_calloc(mp, 1, sizeof(UiObject));
     obj->ctx = uic_context(obj, mp);
     
-    // create native window
-    NSRect frame = NSMakeRect(
-                              300,
-                              200,
-                              window_default_width,
-                              window_default_height);
+    MainWindow *window = [[MainWindow alloc] init:obj];
+    [[WindowManager sharedWindowManager] addWindow:window];
+    window.releasedWhenClosed = false;
     
-    /*
-    UiCocoaWindow *window = [[UiCocoaWindow alloc] initWithContentRect:frame
-                                styleMask:NSTitledWindowMask | NSResizableWindowMask |
-                                NSClosableWindowMask | NSMiniaturizableWindowMask
-                                backing:NSBackingStoreBuffered
-                                defer:false];
-    */
-    UiCocoaWindow *window = [[UiCocoaWindow alloc] init:frame object:obj];
-    
-    NSString *titleStr = [[NSString alloc] initWithUTF8String:title];
-    [window setTitle:titleStr];
-    
-    UiMenuDelegate *menuDelegate = ui_menu_delegate();
-    [window setMenuItems: [menuDelegate items]];
-    [window setMenuItemLists: [menuDelegate lists]];
-    
-    NSToolbar *toolbar = ui_create_toolbar(obj);
-    [window setToolbar: toolbar];
-    
-    obj->widget = (NSView*)window;
-    obj->window = window_data;
-    obj->container = ui_window_container(obj, window);
-    
+    obj->wobj = (__bridge void*)window;
     
     return obj;
 }
 
-void ui_close(UiObject *obj) {
-    // TODO
+UiObject* ui_window(const char *title, void *window_data) {
+    UiObject *obj = create_window(title, FALSE);
+    obj->window = window_data;
+    return obj;
 }
 
-char* ui_openfiledialog(UiObject *obj) {
-    NSOpenPanel* op = [NSOpenPanel openPanel];
-    if ([op runModal] == NSOKButton) {
-        NSArray *urls = [op URLs];
-        NSURL *url = [urls objectAtIndex:0];
-        
-        const char *str = [[url path] UTF8String];
-        return (char*)strdup(str);
-    }
-    return NULL;
+UiObject* ui_simple_window(const char *title, void *window_data) {
+    UiObject *obj = create_window(title, TRUE);
+    obj->window = window_data;
+    return obj;
 }
-
-char* ui_savefiledialog(UiObject *obj) {
-    NSSavePanel* sp = [NSSavePanel savePanel];
-    if ([sp runModal] == NSOKButton) {
-        NSURL *url = [sp URL];
-        
-        const char *str = [[url path] UTF8String];
-        return (char*)strdup(str);
-    }
-    return NULL;
-}
--- a/ui/common/menu.c	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/common/menu.c	Wed Dec 04 08:55:49 2024 +0100
@@ -30,6 +30,7 @@
 
 #include <stdarg.h>
 #include <string.h>
+#include <stdio.h>
 
 #include <cx/linked_list.h>
 #include <cx/array_list.h>
--- a/ui/common/object.c	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/common/object.c	Wed Dec 04 08:55:49 2024 +0100
@@ -32,6 +32,8 @@
 #include "object.h"
 #include "context.h"
 
+#include "../ui/container.h"
+
 void ui_end(UiObject *obj) {
     if(!obj->next) {
         return;
@@ -49,6 +51,15 @@
     }
 }
 
+void ui_end_new(UiObject *obj) {
+    if(!obj->container_end) {
+        return;
+    }
+    UiContainerX *rm = obj->container_end;
+    uic_object_pop_container(obj);
+    ui_free(obj->ctx, rm);
+}
+
 void ui_object_ref(UiObject *obj) {
     obj->ref++;
 }
@@ -109,3 +120,23 @@
 UiContainer* uic_get_current_container(UiObject *obj) {
     return uic_current_obj(obj)->container;
 }
+
+void uic_object_push_container(UiObject *toplevel, UiContainerX *newcontainer) {
+    newcontainer->prev = toplevel->container_end;
+    if(toplevel->container_end) {
+        toplevel->container_end->next = newcontainer;
+        toplevel->container_end = newcontainer;
+    } else {
+        toplevel->container_begin = newcontainer;
+        toplevel->container_end = newcontainer;
+    }
+}
+
+void uic_object_pop_container(UiObject *toplevel) {
+    toplevel->container_end = toplevel->container_end->prev;
+    if(toplevel->container_end) {
+        toplevel->container_end->next = NULL;
+    } else {
+        toplevel->container_begin = NULL;
+    }
+}
--- a/ui/common/object.h	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/common/object.h	Wed Dec 04 08:55:49 2024 +0100
@@ -42,7 +42,11 @@
 void uic_obj_add(UiObject *toplevel, UiObject *ctobj);
 UiObject* uic_current_obj(UiObject *toplevel);
 
-UiContainer* uic_get_current_container(UiObject *obj);;
+UiContainer* uic_get_current_container(UiObject *obj); // deprecated
+
+void uic_object_push_container(UiObject *toplevel, UiContainerX *newcontainer);
+void uic_object_pop_container(UiObject *toplevel);
+
 
 
 #ifdef	__cplusplus
--- a/ui/common/threadpool.c	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/common/threadpool.c	Wed Dec 04 08:55:49 2024 +0100
@@ -29,10 +29,12 @@
 #include "threadpool.h"
 #include "context.h"
 
-#include <pthread.h>
-
 #ifndef _WIN32
 
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
 
 static threadpool_job kill_job;
 
--- a/ui/common/threadpool.h	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/common/threadpool.h	Wed Dec 04 08:55:49 2024 +0100
@@ -31,6 +31,10 @@
 
 #include "../ui/toolkit.h"
 
+#ifndef _WIN32
+#include <pthread.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
--- a/ui/ui/container.h	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/ui/container.h	Wed Dec 04 08:55:49 2024 +0100
@@ -142,6 +142,13 @@
 } UiHeaderbarArgs;
 
 
+struct UiContainerX {
+    void *container;
+    int close;
+    UiContainerX *prev;
+    UiContainerX *next;
+};
+
 
 #define UI_CTN(obj, ctn) for(ctn;ui_container_finish(obj);ui_container_begin_close(obj))
 
@@ -169,7 +176,8 @@
 #define ui_headerbar_center(obj) for(ui_headerbar_center_create(obj);ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_headerbar_end(obj) for(ui_headerbar_end_create(obj);ui_container_finish(obj);ui_container_begin_close(obj))
 
-UIEXPORT void ui_end(UiObject *obj);
+UIEXPORT void ui_end(UiObject *obj); // deprecated
+UIEXPORT void ui_end_new(UiObject *obj); // TODO: rename to ui_end
     
 UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args);
 UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args);
--- a/ui/ui/toolkit.h	Sat Nov 30 20:33:16 2024 +0100
+++ b/ui/ui/toolkit.h	Wed Dec 04 08:55:49 2024 +0100
@@ -33,14 +33,13 @@
 
 #ifdef UI_COCOA
 
+#include <stdlib.h>
 #ifdef __OBJC__
 #import <Cocoa/Cocoa.h>
-#define UIWIDGET NSView*
-#define UIMENU   NSMenu*
-#else
-typedef void* UIWIDGET;
-typedef void* UIMENU;
 #endif
+typedef void* UIWIDGET; // NSView*
+typedef void* UIWINDOW; // NSWindow*
+typedef void* UIMENU;   // NSMenu*
 
 #elif UI_GTK2 || UI_GTK3 || UI_GTK4
 
@@ -155,6 +154,7 @@
 typedef int UiBool;
 
 typedef struct UiObject     UiObject;
+typedef struct UiContainerX UiContainerX;
 typedef struct UiEvent      UiEvent;
 typedef struct UiMouseEvent UiMouseEvent;
 typedef struct UiObserver   UiObserver;
@@ -215,7 +215,7 @@
      */
     UIWIDGET    widget;
 
-#ifdef UI_WINUI
+#if defined(UI_COCOA) || defined(UI_WINUI)
     /*
      * native window object 
      */
@@ -233,11 +233,18 @@
     UiContext   *ctx;
     
     /*
-     * container interface
+     * container interface (deprecated)
      */
     UiContainer *container;
     
     /*
+     * container list
+     * TODO: remove old UiContainer and rename UiContainerX to UiContainer
+     */
+    UiContainerX *container_begin;
+    UiContainerX *container_end;
+    
+    /*
      * next container object
      */
     UiObject    *next;
@@ -440,7 +447,7 @@
 UIEXPORT void ui_onopen(ui_callback f, void *userdata);
 UIEXPORT void ui_onexit(ui_callback f, void *userdata);
 
-UIEXPORT void ui_main();
+UIEXPORT void ui_main(void);
 UIEXPORT void ui_show(UiObject *obj);
 UIEXPORT void ui_close(UiObject *obj);
 

mercurial