From 8f4976780f683dc436c3098e36113ee3ad5119d9 Mon Sep 17 00:00:00 2001
From: Olaf Wintermann
Date: Sat, 19 Jul 2025 21:20:29 +0200
Subject: [PATCH] adjust UI code to new toolkit version
---
configure | 400 ++++++----
make/Makefile.mk | 1 +
make/cc.mk | 10 +-
make/clang.mk | 8 +-
make/configure.vm | 444 +++++++----
make/gcc.mk | 8 +-
make/project.xml | 6 +
make/suncc.mk | 8 +-
make/toolchain.sh | 59 +-
make/uwproj.xsd | 31 +-
mizunara/Makefile | 4 +-
mizunara/window.c | 23 +-
mizunara/window.h | 4 +-
ucx/Makefile | 12 +-
ucx/allocator.c | 21 +-
ucx/array_list.c | 130 ++--
ucx/buffer.c | 80 +-
ucx/cx/allocator.h | 78 +-
ucx/cx/array_list.h | 24 +-
ucx/cx/buffer.h | 36 +-
ucx/cx/common.h | 20 +-
ucx/cx/hash_map.h | 2 +-
ucx/cx/linked_list.h | 6 +-
ucx/cx/list.h | 257 ++++++-
ucx/cx/mempool.h | 262 ++++++-
ucx/cx/printf.h | 8 +-
ucx/cx/properties.h | 10 +-
ucx/cx/string.h | 88 ++-
ucx/cx/tree.h | 28 +-
ucx/json.c | 28 +-
ucx/linked_list.c | 38 +-
ucx/list.c | 35 +-
ucx/mempool.c | 641 ++++++++++++++--
ucx/printf.c | 40 +-
ucx/properties.c | 4 +-
ucx/streams.c | 5 +-
ucx/string.c | 221 ++----
ucx/tree.c | 20 +-
ui/Makefile | 7 +-
ui/common/args.c | 1586 ++++++++++++++++++++++++++++++++++++++++
ui/common/args.h | 372 ++++++++++
ui/common/context.c | 16 +-
ui/common/context.h | 10 +-
ui/common/document.c | 39 +-
ui/common/menu.c | 74 +-
ui/common/object.c | 52 +-
ui/common/object.h | 9 +
ui/common/objs.mk | 3 +-
ui/common/threadpool.c | 1 +
ui/common/toolbar.c | 44 +-
ui/common/types.c | 94 ++-
ui/common/types.h | 5 +-
ui/common/wrapper.c | 220 ++++++
ui/common/wrapper.h | 84 +++
ui/gtk/Makefile | 6 +-
ui/gtk/button.c | 94 +--
ui/gtk/container.c | 252 ++++---
ui/gtk/container.h | 38 +-
ui/gtk/display.c | 56 +-
ui/gtk/entry.c | 41 +-
ui/gtk/graphics.c | 2 +-
ui/gtk/image.c | 51 +-
ui/gtk/list.c | 313 ++++----
ui/gtk/list.h | 1 +
ui/gtk/menu.c | 4 +
ui/gtk/range.c | 4 +-
ui/gtk/text.c | 109 +--
ui/gtk/toolbar.c | 2 +
ui/gtk/toolkit.c | 1 +
ui/gtk/toolkit.h | 1 +
ui/gtk/webview.c | 19 +-
ui/gtk/widget.c | 8 +-
ui/gtk/window.c | 17 +-
ui/ui/button.h | 24 +-
ui/ui/container.h | 119 +--
ui/ui/display.h | 26 +-
ui/ui/entry.h | 6 +-
ui/ui/icons.h | 4 +
ui/ui/image.h | 6 +-
ui/ui/menu.h | 24 +-
ui/ui/text.h | 26 +-
ui/ui/toolbar.h | 14 +-
ui/ui/toolkit.h | 64 +-
ui/ui/tree.h | 57 +-
ui/ui/webview.h | 4 +-
ui/ui/widget.h | 18 +-
86 files changed, 5563 insertions(+), 1564 deletions(-)
create mode 100644 ui/common/args.c
create mode 100644 ui/common/args.h
create mode 100644 ui/common/wrapper.c
create mode 100644 ui/common/wrapper.h
diff --git a/configure b/configure
index 3f1227f..cb58561 100755
--- a/configure
+++ b/configure
@@ -1,40 +1,47 @@
#!/bin/sh
-# create temporary directory
-TEMP_DIR=".tmp-`uname -n`"
-rm -Rf "$TEMP_DIR"
-if mkdir -p "$TEMP_DIR"; then
- :
-else
- echo "Cannot create tmp dir $TEMP_DIR"
- echo "Abort"
- exit 1
-fi
-touch "$TEMP_DIR/options"
-touch "$TEMP_DIR/features"
-# define standard variables
-# also define standard prefix (this is where we will search for config.site)
-prefix=/usr
-exec_prefix=
-bindir=
-sbindir=
-libdir=
-libexecdir=
-datarootdir=
-datadir=
-sysconfdir=
-sharedstatedir=
-localstatedir=
-runstatedir=
-includedir=
-infodir=
-localedir=
-mandir=
-
-# custom variables
-
-# features
+# some utility functions
+isplatform()
+{
+ for p in $PLATFORM
+ do
+ if [ "$p" = "$1" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+notisplatform()
+{
+ for p in $PLATFORM
+ do
+ if [ "$p" = "$1" ]; then
+ return 1
+ fi
+ done
+ return 0
+}
+istoolchain()
+{
+ for t in $TOOLCHAIN
+ do
+ if [ "$t" = "$1" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+notistoolchain()
+{
+ for t in $TOOLCHAIN
+ do
+ if [ "$t" = "$1" ]; then
+ return 1
+ fi
+ done
+ return 0
+}
# clean abort
abort_configure()
@@ -43,6 +50,37 @@ abort_configure()
exit 1
}
+# Test for availability of pkg-config
+PKG_CONFIG=`command -v pkg-config`
+: ${PKG_CONFIG:="false"}
+
+# Simple uname based platform detection
+# $PLATFORM is used for platform dependent dependency selection
+OS=`uname -s`
+OS_VERSION=`uname -r`
+ARCH=`uname -m`
+printf "detect platform... "
+if [ "$OS" = "SunOS" ]; then
+ PLATFORM="solaris sunos unix svr4"
+elif [ "$OS" = "Linux" ]; then
+ PLATFORM="linux unix"
+elif [ "$OS" = "FreeBSD" ]; then
+ PLATFORM="freebsd bsd unix"
+elif [ "$OS" = "OpenBSD" ]; then
+ PLATFORM="openbsd bsd unix"
+elif [ "$OS" = "NetBSD" ]; then
+ PLATFORM="netbsd bsd unix"
+elif [ "$OS" = "Darwin" ]; then
+ PLATFORM="macos osx bsd unix"
+elif echo "$OS" | grep -i "MINGW" > /dev/null; then
+ PLATFORM="windows mingw"
+fi
+: ${PLATFORM:="unix"}
+
+PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -`
+echo "$PLATFORM_NAME"
+
+
# help text
printhelp()
{
@@ -50,7 +88,7 @@ printhelp()
cat << __EOF__
Installation directories:
--prefix=PREFIX path prefix for architecture-independent files
- [/usr]
+ [$prefix]
--exec-prefix=EPREFIX path prefix for architecture-dependent files
[PREFIX]
@@ -69,14 +107,52 @@ Installation directories:
--mandir=DIR man documentation [DATAROOTDIR/man]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
-Options:
+Build Types:
--debug add extra compile flags for debug builds
--release add extra compile flags for release builds
+
+Options:
--toolkit=(libadwaita|gtk4|gtk3|gtk2|cocoa)
__EOF__
}
+# create temporary directory
+TEMP_DIR=".tmp-`uname -n`"
+rm -Rf "$TEMP_DIR"
+if mkdir -p "$TEMP_DIR"; then
+ :
+else
+ echo "Cannot create tmp dir $TEMP_DIR"
+ echo "Abort"
+ exit 1
+fi
+touch "$TEMP_DIR/options"
+touch "$TEMP_DIR/features"
+
+# define standard variables
+# also define standard prefix (this is where we will search for config.site)
+prefix=/usr
+exec_prefix=
+bindir=
+sbindir=
+libdir=
+libexecdir=
+datarootdir=
+datadir=
+sysconfdir=
+sharedstatedir=
+localstatedir=
+runstatedir=
+includedir=
+infodir=
+localedir=
+mandir=
+
+# custom variables
+
+# features
+
#
# parse arguments
#
@@ -99,10 +175,11 @@ do
"--infodir="*) infodir=${ARG#--infodir=} ;;
"--mandir"*) mandir=${ARG#--mandir} ;;
"--localedir"*) localedir=${ARG#--localedir} ;;
- "--help"*) printhelp; abort_configure ;;
- "--debug") BUILD_TYPE="debug" ;;
- "--release") BUILD_TYPE="release" ;;
+ "--help"*) printhelp; abort_configure ;;
+ "--debug") BUILD_TYPE="debug" ;;
+ "--release") BUILD_TYPE="release" ;;
"--toolkit="*) OPT_TOOLKIT=${ARG#--toolkit=} ;;
+ "--toolkit") echo "option '$ARG' needs a value:"; echo " $ARG=(libadwaita|gtk4|gtk3|gtk2|cocoa)"; abort_configure ;;
"-"*) echo "unknown option: $ARG"; abort_configure ;;
esac
done
@@ -126,6 +203,22 @@ done
: ${mandir:='${datarootdir}/man'}
: ${localedir:='${datarootdir}/locale'}
+# remember the above values and compare them later
+orig_bindir="$bindir"
+orig_sbindir="$sbindir"
+orig_libdir="$libdir"
+orig_libexecdir="$libexecdir"
+orig_datarootdir="$datarootdir"
+orig_datadir="$datadir"
+orig_sysconfdir="$sysconfdir"
+orig_sharedstatedir="$sharedstatedir"
+orig_localstatedir="$localstatedir"
+orig_runstatedir="$runstatedir"
+orig_includedir="$includedir"
+orig_infodir="$infodir"
+orig_mandir="$mandir"
+orig_localedir="$localedir"
+
# check if a config.site exists and load it
if [ -n "$CONFIG_SITE" ]; then
# CONFIG_SITE may contain space separated file names
@@ -142,77 +235,29 @@ elif [ -f "$prefix/etc/config.site" ]; then
printf "loading site defaults... "
. "$prefix/etc/config.site"
echo ok
-fi
-
-# Test for availability of pkg-config
-PKG_CONFIG=`command -v pkg-config`
-: ${PKG_CONFIG:="false"}
-
-# Simple uname based platform detection
-# $PLATFORM is used for platform dependent dependency selection
-OS=`uname -s`
-OS_VERSION=`uname -r`
-printf "detect platform... "
-if [ "$OS" = "SunOS" ]; then
- PLATFORM="solaris sunos unix svr4"
-elif [ "$OS" = "Linux" ]; then
- PLATFORM="linux unix"
-elif [ "$OS" = "FreeBSD" ]; then
- PLATFORM="freebsd bsd unix"
-elif [ "$OS" = "OpenBSD" ]; then
- PLATFORM="openbsd bsd unix"
-elif [ "$OS" = "NetBSD" ]; then
- PLATFORM="netbsd bsd unix"
-elif [ "$OS" = "Darwin" ]; then
- PLATFORM="macos osx bsd unix"
-elif echo "$OS" | grep -i "MINGW" > /dev/null; then
- PLATFORM="windows mingw"
-fi
-: ${PLATFORM:="unix"}
-
-PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -`
-echo "$PLATFORM_NAME"
-
-isplatform()
-{
- for p in $PLATFORM
- do
- if [ "$p" = "$1" ]; then
- return 0
- fi
- done
- return 1
-}
-notisplatform()
-{
- for p in $PLATFORM
- do
- if [ "$p" = "$1" ]; then
- return 1
- fi
- done
- return 0
-}
-istoolchain()
-{
- for t in $TOOLCHAIN
- do
- if [ "$t" = "$1" ]; then
- return 0
- fi
- done
- return 1
-}
-notistoolchain()
-{
- for t in $TOOLCHAIN
- do
- if [ "$t" = "$1" ]; then
- return 1
+else
+ # try to detect the correct libdir on our own, except it was changed by the user
+ if test "$libdir" = '${exec_prefix}/lib'; then
+ if [ "$OS" = "SunOS" ]; then
+ test -d "${exec_prefix}/lib/amd64" && libdir='${exec_prefix}/lib/amd64'
+ else
+ # check if the standard libdir even exists
+ if test -d "${exec_prefix}/lib" ; then
+ :
+ else
+ # if it does not, maybe a lib32 exists
+ test -d "${exec_prefix}/lib32" && libdir='${exec_prefix}/lib32'
+ fi
+ # now check if there is a special 64bit libdir that we should use
+ for i in x86_64 ppc64 s390x aarch64 aarch64_be arm64 ; do
+ if [ $ARCH = $i ]; then
+ test -d "${exec_prefix}/lib64" && libdir='${exec_prefix}/lib64'
+ break
+ fi
+ done
fi
- done
- return 0
-}
+ fi
+fi
# generate vars.mk
@@ -649,9 +694,9 @@ echo > "$TEMP_DIR/flags.mk"
DEPENDENCIES_FAILED=
ERROR=0
# unnamed dependencies
-TEMP_CFLAGS=
-TEMP_CXXFLAGS=
-TEMP_LDFLAGS=
+TEMP_CFLAGS="$CFLAGS"
+TEMP_CXXFLAGS="$CXXFLAGS"
+TEMP_LDFLAGS="$LDFLAGS"
while true
do
while true
@@ -676,6 +721,7 @@ do
cat >> "$TEMP_DIR/make.mk" << __EOF__
OBJ_EXT = .o
LIB_EXT = .a
+SHLIB_EXT = .dylib
LIB_PREFIX = lib
PACKAGE_SCRIPT = package_osx.sh
__EOF__
@@ -697,6 +743,7 @@ do
cat >> "$TEMP_DIR/make.mk" << __EOF__
OBJ_EXT = .o
LIB_EXT = .a
+SHLIB_EXT = .so
LIB_PREFIX = lib
PACKAGE_SCRIPT = package_unix.sh
__EOF__
@@ -705,6 +752,19 @@ __EOF__
break
done
while true
+do
+ while true
+ do
+
+ cat >> "$TEMP_DIR/make.mk" << __EOF__
+BUILD_BIN_DIR = bin
+BUILD_LIB_DIR = lib
+__EOF__
+ break
+ done
+ break
+done
+while true
do
if notisplatform "bsd"; then
break
@@ -719,6 +779,16 @@ do
break
done
+# build type
+if [ "$BUILD_TYPE" = "debug" ]; then
+ TEMP_CFLAGS="\${DEBUG_CFLAGS} $TEMP_CFLAGS"
+ TEMP_CXXFLAGS="\${DEBUG_CXXFLAGS} $TEMP_CXXFLAGS"
+fi
+if [ "$BUILD_TYPE" = "release" ]; then
+ TEMP_CFLAGS="\${RELEASE_CFLAGS} $TEMP_CFLAGS"
+ TEMP_CXXFLAGS="\${RELEASE_CXXFLAGS} $TEMP_CXXFLAGS"
+fi
+
# add general dependency flags to flags.mk
echo "# general flags" >> "$TEMP_DIR/flags.mk"
if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then
@@ -842,22 +912,6 @@ fi
if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then
echo "DAV_CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk"
fi
-if [ "$BUILD_TYPE" = "debug" ]; then
- if [ -n "$lang_c" ]; then
- echo 'DAV_CFLAGS += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
- if [ -n "$lang_cpp" ]; then
- echo 'DAV_CXXFLAGS += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
-fi
-if [ "$BUILD_TYPE" = "release" ]; then
- if [ -n "$lang_c" ]; then
- echo 'DAV_CFLAGS += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
- if [ -n "$lang_cpp" ]; then
- echo 'DAV_CXXFLAGS += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
-fi
if [ -n "${TEMP_LDFLAGS}" ]; then
echo "DAV_LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk"
fi
@@ -969,6 +1023,11 @@ else
ERROR=1
DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED"
fi
+ else
+ echo
+ echo "Invalid option value - usage:"
+ echo " --toolkit=(libadwaita|gtk4|gtk3|gtk2|cocoa)"
+ abort_configure
fi
fi
@@ -978,22 +1037,6 @@ fi
if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then
echo "TK_CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk"
fi
-if [ "$BUILD_TYPE" = "debug" ]; then
- if [ -n "$lang_c" ]; then
- echo 'TK_CFLAGS += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
- if [ -n "$lang_cpp" ]; then
- echo 'TK_CXXFLAGS += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
-fi
-if [ "$BUILD_TYPE" = "release" ]; then
- if [ -n "$lang_c" ]; then
- echo 'TK_CFLAGS += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
- if [ -n "$lang_cpp" ]; then
- echo 'TK_CXXFLAGS += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
-fi
if [ -n "${TEMP_LDFLAGS}" ]; then
echo "TK_LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk"
fi
@@ -1009,20 +1052,81 @@ fi
echo "configure finished"
echo
+echo "Toolchain"
+echo " name: $TOOLCHAIN_NAME"
+if [ -n "$TOOLCHAIN_CC" ]; then
+ echo " cc: $TOOLCHAIN_CC"
+fi
+if [ -n "$TOOLCHAIN_CXX" ]; then
+ echo " cxx: $TOOLCHAIN_CXX"
+fi
+if [ -n "$TOOLCHAIN_WSIZE" ]; then
+ echo " word size: $TOOLCHAIN_WSIZE bit"
+fi
+if [ -n "$TOOLCHAIN_CSTD" ]; then
+ echo " default C std: $TOOLCHAIN_CSTD"
+fi
+echo
echo "Build Config:"
-echo " PREFIX: $prefix"
-echo " TOOLCHAIN: $TOOLCHAIN_NAME"
+echo " prefix: $prefix"
+echo " exec_prefix: $exec_prefix"
+if [ "$orig_bindir" != "$bindir" ]; then
+ echo " bindir: $bindir"
+fi
+if [ "$orig_sbindir" != "$sbindir" ]; then
+ echo " sbindir: $sbindir"
+fi
+if [ "$orig_libdir" != "$libdir" ]; then
+ echo " libdir: $libdir"
+fi
+if [ "$orig_libexecdir" != "$libexecdir" ]; then
+ echo " libexecdir: $libexecdir"
+fi
+if [ "$orig_datarootdir" != "$datarootdir" ]; then
+ echo " datarootdir: $datarootdir"
+fi
+if [ "$orig_datadir" != "$datadir" ]; then
+ echo " datadir: $datadir"
+fi
+if [ "$orig_sysconfdir" != "$sysconfdir" ]; then
+ echo " sysconfdir: $sysconfdir"
+fi
+if [ "$orig_sharedstatedir" != "$sharedstatedir" ]; then
+ echo " sharedstatedir: $sharedstatedir"
+fi
+if [ "$orig_localstatedir" != "$localstatedir" ]; then
+ echo " localstatedir: $localstatedir"
+fi
+if [ "$orig_runstatedir" != "$runstatedir" ]; then
+ echo " runstatedir: $runstatedir"
+fi
+if [ "$orig_includedir" != "$includedir" ]; then
+ echo " includedir: $includedir"
+fi
+if [ "$orig_infodir" != "$infodir" ]; then
+ echo " infodir: $infodir"
+fi
+if [ "$orig_mandir" != "$mandir" ]; then
+ echo " mandir: $mandir"
+fi
+if [ "$orig_localedir" != "$localedir" ]; then
+ echo " localedir: $localedir"
+fi
+echo
echo "Options:"
cat "$TEMP_DIR/options"
echo
# generate the config.mk file
+pwd=`pwd`
cat > "$TEMP_DIR/config.mk" << __EOF__
#
-# config.mk generated by configure
+# config.mk generated by:
+# pwd: $pwd
+# $0 $@
#
__EOF__
write_toolchain_defaults "$TEMP_DIR/toolchain.mk"
-cat "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk
+cat "$TEMP_DIR/config.mk" "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk
rm -Rf "$TEMP_DIR"
diff --git a/make/Makefile.mk b/make/Makefile.mk
index 11b8e73..d791cbf 100644
--- a/make/Makefile.mk
+++ b/make/Makefile.mk
@@ -32,6 +32,7 @@ BUILD_ROOT = ./
include config.mk
BUILD_DIRS = build/bin build/lib
+BUILD_DIRS += build/ucx
BUILD_DIRS += build/libidav
BUILD_DIRS += build/mizunara
BUILD_DIRS += build/mizucp
diff --git a/make/cc.mk b/make/cc.mk
index 149bde6..72e3155 100644
--- a/make/cc.mk
+++ b/make/cc.mk
@@ -4,11 +4,11 @@
CFLAGS =
CXXFLAGS =
-DEBUG_CC_FLAGS = -g
-DEBUG_CXX_FLAGS = -g
-RELEASE_CC_FLAGS = -O3 -DNDEBUG
-RELEASE_CXX_FLAGS = -O3 -DNDEBUG
+DEBUG_CFLAGS = -g
+DEBUG_CXXFLAGS = -g
+RELEASE_CFLAGS = -O3 -DNDEBUG
+RELEASE_CXXFLAGS = -O3 -DNDEBUG
LDFLAGS =
SHLIB_CFLAGS = -fPIC
-SHLIB_LDFLAGS = -shared
\ No newline at end of file
+SHLIB_LDFLAGS = -shared
diff --git a/make/clang.mk b/make/clang.mk
index 772ebb7..fb18443 100644
--- a/make/clang.mk
+++ b/make/clang.mk
@@ -4,10 +4,10 @@
CFLAGS =
CXXFLAGS =
-DEBUG_CC_FLAGS = -g
-DEBUG_CXX_FLAGS = -g
-RELEASE_CC_FLAGS = -O3 -DNDEBUG
-RELEASE_CXX_FLAGS = -O3 -DNDEBUG
+DEBUG_CFLAGS = -g
+DEBUG_CXXFLAGS = -g
+RELEASE_CFLAGS = -O3 -DNDEBUG
+RELEASE_CXXFLAGS = -O3 -DNDEBUG
LDFLAGS =
SHLIB_CFLAGS = -fPIC
diff --git a/make/configure.vm b/make/configure.vm
index b8acad3..7be6ed7 100644
--- a/make/configure.vm
+++ b/make/configure.vm
@@ -1,52 +1,48 @@
#!/bin/sh
-# create temporary directory
-TEMP_DIR=".tmp-`uname -n`"
-rm -Rf "$TEMP_DIR"
-if mkdir -p "$TEMP_DIR"; then
- :
-else
- echo "Cannot create tmp dir $TEMP_DIR"
- echo "Abort"
- exit 1
-fi
-touch "$TEMP_DIR/options"
-touch "$TEMP_DIR/features"
-
-# define standard variables
-# also define standard prefix (this is where we will search for config.site)
-prefix=/usr
-exec_prefix=
-bindir=
-sbindir=
-libdir=
-libexecdir=
-datarootdir=
-datadir=
-sysconfdir=
-sharedstatedir=
-localstatedir=
-runstatedir=
-includedir=
-infodir=
-localedir=
-mandir=
-
-# custom variables
-#foreach( $var in $vars )
-#if( $var.exec )
-${var.varName}=`${var.value}`
-#else
-${var.varName}="${var.value}"
-#end
-#end
-
-# features
-#foreach( $feature in $features )
-#if( ${feature.auto} )
-${feature.varName}=auto
-#end
-#end
+#set( $D = '$' )
+#[[
+# some utility functions
+isplatform()
+{
+ for p in $PLATFORM
+ do
+ if [ "$p" = "$1" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+notisplatform()
+{
+ for p in $PLATFORM
+ do
+ if [ "$p" = "$1" ]; then
+ return 1
+ fi
+ done
+ return 0
+}
+istoolchain()
+{
+ for t in $TOOLCHAIN
+ do
+ if [ "$t" = "$1" ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+notistoolchain()
+{
+ for t in $TOOLCHAIN
+ do
+ if [ "$t" = "$1" ]; then
+ return 1
+ fi
+ done
+ return 0
+}
# clean abort
abort_configure()
@@ -55,6 +51,37 @@ abort_configure()
exit 1
}
+# Test for availability of pkg-config
+PKG_CONFIG=`command -v pkg-config`
+: ${PKG_CONFIG:="false"}
+
+# Simple uname based platform detection
+# $PLATFORM is used for platform dependent dependency selection
+OS=`uname -s`
+OS_VERSION=`uname -r`
+ARCH=`uname -m`
+printf "detect platform... "
+if [ "$OS" = "SunOS" ]; then
+ PLATFORM="solaris sunos unix svr4"
+elif [ "$OS" = "Linux" ]; then
+ PLATFORM="linux unix"
+elif [ "$OS" = "FreeBSD" ]; then
+ PLATFORM="freebsd bsd unix"
+elif [ "$OS" = "OpenBSD" ]; then
+ PLATFORM="openbsd bsd unix"
+elif [ "$OS" = "NetBSD" ]; then
+ PLATFORM="netbsd bsd unix"
+elif [ "$OS" = "Darwin" ]; then
+ PLATFORM="macos osx bsd unix"
+elif echo "$OS" | grep -i "MINGW" > /dev/null; then
+ PLATFORM="windows mingw"
+fi
+: ${PLATFORM:="unix"}
+
+PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -`
+echo "$PLATFORM_NAME"
+]]#
+
# help text
printhelp()
{
@@ -62,7 +89,7 @@ printhelp()
cat << __EOF__
Installation directories:
--prefix=PREFIX path prefix for architecture-independent files
- [/usr]
+ [${D}prefix]
--exec-prefix=EPREFIX path prefix for architecture-dependent files
[PREFIX]
@@ -81,30 +108,90 @@ Installation directories:
--mandir=DIR man documentation [DATAROOTDIR/man]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
-#if( $options.size() > 0 )
-Options:
+Build Types:
--debug add extra compile flags for debug builds
--release add extra compile flags for release builds
+#if( $options.size() > 0 )
+
+Options:
#foreach( $opt in $options )
--${opt.argument}=${opt.valuesString}
#end
-
#end
#if( $features.size() > 0 )
+
Optional Features:
#foreach( $feature in $features )
${feature.helpText}
#end
-
#end
+
__EOF__
}
+# create temporary directory
+TEMP_DIR=".tmp-`uname -n`"
+rm -Rf "$TEMP_DIR"
+if mkdir -p "$TEMP_DIR"; then
+ :
+else
+ echo "Cannot create tmp dir $TEMP_DIR"
+ echo "Abort"
+ exit 1
+fi
+touch "$TEMP_DIR/options"
+touch "$TEMP_DIR/features"
+
+# define standard variables
+# also define standard prefix (this is where we will search for config.site)
+prefix=/usr
+exec_prefix=
+bindir=
+sbindir=
+libdir=
+libexecdir=
+datarootdir=
+datadir=
+sysconfdir=
+sharedstatedir=
+localstatedir=
+runstatedir=
+includedir=
+infodir=
+localedir=
+mandir=
+
+# custom variables
+#foreach( $cfg in $config )
+if true \
+#if( $cfg.platform )
+ && isplatform "${cfg.platform}" \
+#end
+#foreach( $np in $cfg.notList )
+ && notisplatform "${np}" \
+#end
+ ; then
+ #foreach( $var in $cfg.vars )
+ #if( $var.exec )
+ ${var.varName}=`${var.value}`
+ #else
+ ${var.varName}="${var.value}"
+ #end
+ #end
+fi
+#end
+
+# features
+#foreach( $feature in $features )
+#if( ${feature.auto} )
+${feature.varName}=auto
+#end
+#end
+
#
# parse arguments
#
BUILD_TYPE="default"
-#set( $D = '$' )
for ARG in "$@"
do
case "$ARG" in
@@ -123,11 +210,12 @@ do
"--infodir="*) infodir=${D}{ARG#--infodir=} ;;
"--mandir"*) mandir=${D}{ARG#--mandir} ;;
"--localedir"*) localedir=${D}{ARG#--localedir} ;;
- "--help"*) printhelp; abort_configure ;;
- "--debug") BUILD_TYPE="debug" ;;
- "--release") BUILD_TYPE="release" ;;
+ "--help"*) printhelp; abort_configure ;;
+ "--debug") BUILD_TYPE="debug" ;;
+ "--release") BUILD_TYPE="release" ;;
#foreach( $opt in $options )
"--${opt.argument}="*) ${opt.varName}=${D}{ARG#--${opt.argument}=} ;;
+ "--${opt.argument}") echo "option '$ARG' needs a value:"; echo " $ARG=${opt.valuesString}"; abort_configure ;;
#end
#foreach( $feature in $features )
"--enable-${feature.arg}") ${feature.varName}=on ;;
@@ -157,6 +245,22 @@ done
: ${mandir:='${datarootdir}/man'}
: ${localedir:='${datarootdir}/locale'}
+# remember the above values and compare them later
+orig_bindir="$bindir"
+orig_sbindir="$sbindir"
+orig_libdir="$libdir"
+orig_libexecdir="$libexecdir"
+orig_datarootdir="$datarootdir"
+orig_datadir="$datadir"
+orig_sysconfdir="$sysconfdir"
+orig_sharedstatedir="$sharedstatedir"
+orig_localstatedir="$localstatedir"
+orig_runstatedir="$runstatedir"
+orig_includedir="$includedir"
+orig_infodir="$infodir"
+orig_mandir="$mandir"
+orig_localedir="$localedir"
+
# check if a config.site exists and load it
if [ -n "$CONFIG_SITE" ]; then
# CONFIG_SITE may contain space separated file names
@@ -173,77 +277,29 @@ elif [ -f "$prefix/etc/config.site" ]; then
printf "loading site defaults... "
. "$prefix/etc/config.site"
echo ok
-fi
-
-# Test for availability of pkg-config
-PKG_CONFIG=`command -v pkg-config`
-: ${PKG_CONFIG:="false"}
-
-# Simple uname based platform detection
-# $PLATFORM is used for platform dependent dependency selection
-OS=`uname -s`
-OS_VERSION=`uname -r`
-printf "detect platform... "
-if [ "$OS" = "SunOS" ]; then
- PLATFORM="solaris sunos unix svr4"
-elif [ "$OS" = "Linux" ]; then
- PLATFORM="linux unix"
-elif [ "$OS" = "FreeBSD" ]; then
- PLATFORM="freebsd bsd unix"
-elif [ "$OS" = "OpenBSD" ]; then
- PLATFORM="openbsd bsd unix"
-elif [ "$OS" = "NetBSD" ]; then
- PLATFORM="netbsd bsd unix"
-elif [ "$OS" = "Darwin" ]; then
- PLATFORM="macos osx bsd unix"
-elif echo "$OS" | grep -i "MINGW" > /dev/null; then
- PLATFORM="windows mingw"
-fi
-: ${PLATFORM:="unix"}
-
-PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -`
-echo "$PLATFORM_NAME"
-
-isplatform()
-{
- for p in $PLATFORM
- do
- if [ "$p" = "$1" ]; then
- return 0
- fi
- done
- return 1
-}
-notisplatform()
-{
- for p in $PLATFORM
- do
- if [ "$p" = "$1" ]; then
- return 1
- fi
- done
- return 0
-}
-istoolchain()
-{
- for t in $TOOLCHAIN
- do
- if [ "$t" = "$1" ]; then
- return 0
- fi
- done
- return 1
-}
-notistoolchain()
-{
- for t in $TOOLCHAIN
- do
- if [ "$t" = "$1" ]; then
- return 1
+else
+ # try to detect the correct libdir on our own, except it was changed by the user
+ if test "$libdir" = '${exec_prefix}/lib'; then
+ if [ "$OS" = "SunOS" ]; then
+ test -d "${exec_prefix}/lib/amd64" && libdir='${exec_prefix}/lib/amd64'
+ else
+ # check if the standard libdir even exists
+ if test -d "${exec_prefix}/lib" ; then
+ :
+ else
+ # if it does not, maybe a lib32 exists
+ test -d "${exec_prefix}/lib32" && libdir='${exec_prefix}/lib32'
+ fi
+ # now check if there is a special 64bit libdir that we should use
+ for i in x86_64 ppc64 s390x aarch64 aarch64_be arm64 ; do
+ if [ $ARCH = $i ]; then
+ test -d "${exec_prefix}/lib64" && libdir='${exec_prefix}/lib64'
+ break
+ fi
+ done
fi
- done
- return 0
-}
+ fi
+fi
]]#
## End of unparsed content **
@@ -394,9 +450,9 @@ DEPENDENCIES_FAILED=
ERROR=0
#if( $dependencies.size() > 0 )
# unnamed dependencies
-TEMP_CFLAGS=
-TEMP_CXXFLAGS=
-TEMP_LDFLAGS=
+TEMP_CFLAGS="$CFLAGS"
+TEMP_CXXFLAGS="$CXXFLAGS"
+TEMP_LDFLAGS="$LDFLAGS"
#foreach( $dependency in $dependencies )
while true
do
@@ -468,6 +524,16 @@ __EOF__
done
#end
+# build type
+if [ "$BUILD_TYPE" = "debug" ]; then
+ TEMP_CFLAGS="\${DEBUG_CFLAGS} $TEMP_CFLAGS"
+ TEMP_CXXFLAGS="\${DEBUG_CXXFLAGS} $TEMP_CXXFLAGS"
+fi
+if [ "$BUILD_TYPE" = "release" ]; then
+ TEMP_CFLAGS="\${RELEASE_CFLAGS} $TEMP_CFLAGS"
+ TEMP_CXXFLAGS="\${RELEASE_CXXFLAGS} $TEMP_CXXFLAGS"
+fi
+
# add general dependency flags to flags.mk
echo "# general flags" >> "$TEMP_DIR/flags.mk"
if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then
@@ -554,6 +620,35 @@ if [ -n "${D}${feature.varName}" ]; then
unset ${feature.varName}
fi
fi
+if [ -n "${D}${feature.varName}" ]; then
+ :
+#foreach( $def in $feature.defines )
+ TEMP_CFLAGS="$TEMP_CFLAGS ${def.toFlags()}"
+ TEMP_CXXFLAGS="$TEMP_CXXFLAGS ${def.toFlags()}"
+#end
+#if( $feature.hasMake() )
+ cat >> "$TEMP_DIR/make.mk" << __EOF__
+$feature.make
+__EOF__
+#end
+else
+ :
+#foreach( $def in $feature.disabled.defines )
+ TEMP_CFLAGS="$TEMP_CFLAGS ${def.toFlags()}"
+ TEMP_CXXFLAGS="$TEMP_CXXFLAGS ${def.toFlags()}"
+#end
+#if( $feature.disabled.hasMake() )
+ cat >> "$TEMP_DIR/make.mk" << __EOF__
+$feature.disabled.make
+__EOF__
+#end
+#foreach( $dependency in $feature.disabled.dependencies )
+ if dependency_error_$dependency ; then
+ DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED ${dependency} "
+ ERROR=1
+ fi
+#end
+fi
#end
#foreach( $opt in $target.options )
@@ -600,6 +695,11 @@ else
DEPENDENCIES_FAILED="option '${opt.argument}' $DEPENDENCIES_FAILED"
fi
#end
+ else
+ echo
+ echo "Invalid option value - usage:"
+ echo " --${opt.argument}=${opt.valuesString}"
+ abort_configure
fi
fi
#end
@@ -610,22 +710,6 @@ fi
if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then
echo "${target.cxxFlags} += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk"
fi
-if [ "$BUILD_TYPE" = "debug" ]; then
- if [ -n "$lang_c" ]; then
- echo '${target.cFlags} += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
- if [ -n "$lang_cpp" ]; then
- echo '${target.cxxFlags} += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
-fi
-if [ "$BUILD_TYPE" = "release" ]; then
- if [ -n "$lang_c" ]; then
- echo '${target.cFlags} += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
- if [ -n "$lang_cpp" ]; then
- echo '${target.cxxFlags} += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk"
- fi
-fi
if [ -n "${TEMP_LDFLAGS}" ]; then
echo "${target.ldFlags} += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk"
fi
@@ -642,14 +726,73 @@ fi
echo "configure finished"
echo
+echo "Toolchain"
+echo " name: $TOOLCHAIN_NAME"
+if [ -n "$TOOLCHAIN_CC" ]; then
+ echo " cc: $TOOLCHAIN_CC"
+fi
+if [ -n "$TOOLCHAIN_CXX" ]; then
+ echo " cxx: $TOOLCHAIN_CXX"
+fi
+if [ -n "$TOOLCHAIN_WSIZE" ]; then
+ echo " word size: $TOOLCHAIN_WSIZE bit"
+fi
+if [ -n "$TOOLCHAIN_CSTD" ]; then
+ echo " default C std: $TOOLCHAIN_CSTD"
+fi
+echo
echo "Build Config:"
-echo " PREFIX: $prefix"
-echo " TOOLCHAIN: $TOOLCHAIN_NAME"
+echo " prefix: $prefix"
+echo " exec_prefix: $exec_prefix"
+if [ "$orig_bindir" != "$bindir" ]; then
+ echo " bindir: $bindir"
+fi
+if [ "$orig_sbindir" != "$sbindir" ]; then
+ echo " sbindir: $sbindir"
+fi
+if [ "$orig_libdir" != "$libdir" ]; then
+ echo " libdir: $libdir"
+fi
+if [ "$orig_libexecdir" != "$libexecdir" ]; then
+ echo " libexecdir: $libexecdir"
+fi
+if [ "$orig_datarootdir" != "$datarootdir" ]; then
+ echo " datarootdir: $datarootdir"
+fi
+if [ "$orig_datadir" != "$datadir" ]; then
+ echo " datadir: $datadir"
+fi
+if [ "$orig_sysconfdir" != "$sysconfdir" ]; then
+ echo " sysconfdir: $sysconfdir"
+fi
+if [ "$orig_sharedstatedir" != "$sharedstatedir" ]; then
+ echo " sharedstatedir: $sharedstatedir"
+fi
+if [ "$orig_localstatedir" != "$localstatedir" ]; then
+ echo " localstatedir: $localstatedir"
+fi
+if [ "$orig_runstatedir" != "$runstatedir" ]; then
+ echo " runstatedir: $runstatedir"
+fi
+if [ "$orig_includedir" != "$includedir" ]; then
+ echo " includedir: $includedir"
+fi
+if [ "$orig_infodir" != "$infodir" ]; then
+ echo " infodir: $infodir"
+fi
+if [ "$orig_mandir" != "$mandir" ]; then
+ echo " mandir: $mandir"
+fi
+if [ "$orig_localedir" != "$localedir" ]; then
+ echo " localedir: $localedir"
+fi
#if ( $options.size() > 0 )
+echo
echo "Options:"
cat "$TEMP_DIR/options"
#end
#if ( $features.size() > 0 )
+echo
echo "Features:"
#foreach( $feature in $features )
if [ -n "${D}${feature.varName}" ]; then
@@ -662,12 +805,15 @@ fi
echo
# generate the config.mk file
+pwd=`pwd`
cat > "$TEMP_DIR/config.mk" << __EOF__
#
-# config.mk generated by configure
+# config.mk generated by:
+# pwd: $pwd
+# $0 $@
#
__EOF__
write_toolchain_defaults "$TEMP_DIR/toolchain.mk"
-cat "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk
+cat "$TEMP_DIR/config.mk" "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk
rm -Rf "$TEMP_DIR"
diff --git a/make/gcc.mk b/make/gcc.mk
index 5eea8e1..e2f2940 100644
--- a/make/gcc.mk
+++ b/make/gcc.mk
@@ -4,10 +4,10 @@
CFLAGS =
CXXFLAGS =
-DEBUG_CC_FLAGS = -g
-DEBUG_CXX_FLAGS = -g
-RELEASE_CC_FLAGS = -O3 -DNDEBUG
-RELEASE_CXX_FLAGS = -O3 -DNDEBUG
+DEBUG_CFLAGS = -g
+DEBUG_CXXFLAGS = -g
+RELEASE_CFLAGS = -O3 -DNDEBUG
+RELEASE_CXXFLAGS = -O3 -DNDEBUG
LDFLAGS =
SHLIB_CFLAGS = -fPIC
diff --git a/make/project.xml b/make/project.xml
index b2553d3..332310a 100644
--- a/make/project.xml
+++ b/make/project.xml
@@ -100,15 +100,21 @@
OBJ_EXT = .o
LIB_EXT = .a
+ SHLIB_EXT = .dylib
LIB_PREFIX = lib
PACKAGE_SCRIPT = package_osx.sh
OBJ_EXT = .o
LIB_EXT = .a
+ SHLIB_EXT = .so
LIB_PREFIX = lib
PACKAGE_SCRIPT = package_unix.sh
+
+ BUILD_BIN_DIR = bin
+ BUILD_LIB_DIR = lib
+
-I/usr/local/include
diff --git a/make/suncc.mk b/make/suncc.mk
index 38cbb87..8b941d2 100644
--- a/make/suncc.mk
+++ b/make/suncc.mk
@@ -4,10 +4,10 @@
CFLAGS =
CXXFLAGS =
-DEBUG_CC_FLAGS = -g
-DEBUG_CXX_FLAGS = -g
-RELEASE_CC_FLAGS = -O3 -DNDEBUG
-RELEASE_CXX_FLAGS = -O3 -DNDEBUG
+DEBUG_CFLAGS = -g
+DEBUG_CXXFLAGS = -g
+RELEASE_CFLAGS = -O3 -DNDEBUG
+RELEASE_CXXFLAGS = -O3 -DNDEBUG
LDFLAGS =
SHLIB_CFLAGS = -Kpic
diff --git a/make/toolchain.sh b/make/toolchain.sh
index ac5fb68..e68fcc7 100644
--- a/make/toolchain.sh
+++ b/make/toolchain.sh
@@ -17,20 +17,28 @@ unset TOOLCHAIN_CXX
check_c_compiler()
{
+ command -v $1 2>&1 >/dev/null
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
cat > "$TEMP_DIR/test.c" << __EOF__
/* test file */
#include
int main(int argc, char **argv) {
#if defined(_MSC_VER)
- printf("msc\n");
+ printf("toolchain:msc\n");
#elif defined(__clang__)
- printf("clang gnuc\n");
+ printf("toolchain:clang gnuc\n");
#elif defined(__GNUC__)
- printf("gcc gnuc\n");
+ printf("toolchain:gcc gnuc\n");
#elif defined(__sun)
- printf("suncc\n");
+ printf("toolchain:suncc\n");
#else
- printf("unknown\n");
+ printf("toolchain:unknown\n");
+#endif
+ printf("wsize:%d\n", (int)sizeof(void*)*8);
+#ifdef __STDC_VERSION__
+ printf("stdcversion:%d\n", __STDC_VERSION__);
#endif
return 0;
}
@@ -41,21 +49,26 @@ __EOF__
check_cpp_compiler()
{
+ command -v $1 2>&1 >/dev/null
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
cat > "$TEMP_DIR/test.cpp" << __EOF__
/* test file */
#include
int main(int argc, char **argv) {
#if defined(_MSC_VER)
- std::cout << "msc" << std::endl;
+ std::cout << "toolchain:msc" << std::endl;
#elif defined(__clang__)
- std::cout << "clang gnuc" << std::endl;
+ std::cout << "toolchain:clang gnuc" << std::endl;
#elif defined(__GNUC__)
- std::cout << "gcc gnuc" << std::endl;
+ std::cout << "toolchain:gcc gnuc" << std::endl;
#elif defined(__sun)
- std::cout << "suncc" << std::endl;
+ std::cout << "toolchain:suncc" << std::endl;
#else
- std::cout << "cc" << std::endl;
+ std::cout << "toolchain:unknown" << std::endl;
#endif
+ std::cout << "wsize:" << sizeof(void*)*8 << std::endl;
return 0;
}
__EOF__
@@ -113,6 +126,14 @@ check_lib()
fi
}
+parse_toolchain_properties()
+{
+ info_file="$1"
+ TOOLCHAIN=`grep '^toolchain:' "$info_file" | tail -c +11`
+ TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -`
+ TOOLCHAIN_WSIZE=`grep '^wsize:' "$info_file" | tail -c +7`
+}
+
detect_c_compiler()
{
if [ -n "$TOOLCHAIN_CC" ]; then
@@ -122,8 +143,9 @@ detect_c_compiler()
if [ -n "$CC" ]; then
if check_c_compiler "$CC"; then
TOOLCHAIN_CC=$CC
- TOOLCHAIN=`"$TEMP_DIR/checkcc"`
- TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -`
+ "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out"
+ parse_toolchain_properties "$TEMP_DIR/checkcc_out"
+ TOOLCHAIN_CSTD=`grep '^stdcversion:' "$TEMP_DIR/checkcc_out" | tail -c +13`
echo "$CC"
return 0
else
@@ -135,8 +157,9 @@ detect_c_compiler()
do
if check_c_compiler "$COMP"; then
TOOLCHAIN_CC=$COMP
- TOOLCHAIN=`"$TEMP_DIR/checkcc"`
- TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -`
+ "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out"
+ parse_toolchain_properties "$TEMP_DIR/checkcc_out"
+ TOOLCHAIN_CSTD=`grep '^stdcversion:' "$TEMP_DIR/checkcc_out" | tail -c +13`
echo "$COMP"
return 0
fi
@@ -156,8 +179,8 @@ detect_cpp_compiler()
if [ -n "$CXX" ]; then
if check_cpp_compiler "$CXX"; then
TOOLCHAIN_CXX=$CXX
- TOOLCHAIN=`"$TEMP_DIR/checkcc"`
- TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -`
+ "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out"
+ parse_toolchain_properties "$TEMP_DIR/checkcc_out"
echo "$CXX"
return 0
else
@@ -169,8 +192,8 @@ detect_cpp_compiler()
do
if check_cpp_compiler "$COMP"; then
TOOLCHAIN_CXX=$COMP
- TOOLCHAIN=`"$TEMP_DIR/checkcc"`
- TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -`
+ "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out"
+ parse_toolchain_properties "$TEMP_DIR/checkcc_out"
echo "$COMP"
return 0
fi
diff --git a/make/uwproj.xsd b/make/uwproj.xsd
index f702701..a62ddb2 100644
--- a/make/uwproj.xsd
+++ b/make/uwproj.xsd
@@ -3,7 +3,7 @@
xmlns="http://unixwork.de/uwproj"
targetNamespace="http://unixwork.de/uwproj"
elementFormDefault="qualified"
- version="0.2"
+ version="0.3"
>
@@ -17,22 +17,33 @@
-
+
+
- The configuration section.
- Consists of an arbitrary number of var
elements.
+
+ The configuration section.
+ Consists of an arbitrary number of var
elements.
+
+
+ The optional platform
attribute may specify a single platform identifier and
+ the optional not
attribute may specify a comma-separated list of platform identifiers.
+ The configure script shall skip this config declaration if the detected platform is not matching
+ the filter specification of these attributes.
+
+
+
@@ -185,6 +196,9 @@
dependencies
are satisfied.
If a feature is enabled, all define
and make
definitions are
supposed to be applied to the config file.
+ If a feature is disabled, an optional disabled
element may specify which
+ define
and make
definitions are supposed to be applied.
+ There might also be dependencies
when the feature is disabled (e.g. specifying a fallback).
In case the optional default
attribute is set to true, the feature is enabled by default
and is supposed to be automatically disabled (without error) when the dependencies are not satisfied.
The name that is supposed to be used for the --enable and --disable arguments can be optionally
@@ -195,11 +209,18 @@
+
+
+
+
+
+
+
+
-
diff --git a/mizunara/Makefile b/mizunara/Makefile
index 1445ec8..4fb25c1 100644
--- a/mizunara/Makefile
+++ b/mizunara/Makefile
@@ -46,8 +46,8 @@ OBJ = $(SRC:%.c=$(BUILD_ROOT)/build/mizunara/%.$(OBJ_EXT))
all: $(BUILD_ROOT)/build/bin/mizunara
-$(BUILD_ROOT)/build/bin/mizunara: $(OBJ) $(BUILD_ROOT)/build/lib/libuitk.a
- $(CC) -o $(BUILD_ROOT)/build/bin/mizunara$(APP_EXT) $(OBJ) -L$(BUILD_ROOT)/build/lib -luitk -lidav -lucx $(LDFLAGS) $(TK_LDFLAGS) $(DAV_LDFLAGS)
+$(BUILD_ROOT)/build/bin/mizunara: $(OBJ) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT)
+ $(CC) -o $(BUILD_ROOT)/build/bin/mizunara$(APP_EXT) $(OBJ) -L$(BUILD_ROOT)/build/lib -lidav $(LDFLAGS) $(TK_LDFLAGS) $(DAV_LDFLAGS) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/libucx.a $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/libuitk.a
$(BUILD_ROOT)/build/mizunara/%.$(OBJ_EXT): %.c
$(CC) $(CFLAGS) $(TK_CFLAGS) -o $@ -c $<
diff --git a/mizunara/window.c b/mizunara/window.c
index 6d996cc..e004583 100644
--- a/mizunara/window.c
+++ b/mizunara/window.c
@@ -81,13 +81,18 @@ UiObject* window_create(const char *url) {
{ .value = wdata->default_dirs, .userdata = window_sidebar_user_dirs_item },
{ .value = wdata->user_dirs, .userdata = window_sidebar_user_dirs_item, .separator = TRUE }
};
- ui_sourcelist(obj, .sublists = sublists, .numsublists = 2, .getvalue = window_sidebar_getvalue, .onactivate = action_sourcelist_activate);
+ ui_sourcelist(obj,
+ .sublists = sublists,
+ .numsublists = 2,
+ .getvalue = window_sidebar_getvalue,
+ .onactivate = action_sourcelist_activate,
+ .fill = TRUE);
}
- ui_hbox(obj, .spacing = 4, .fill = UI_OFF) {
+ ui_hbox(obj, .spacing = 4) {
ui_button(obj, .style_class = "flat", .icon = UI_ICON_GO_BACK);
ui_button(obj, .style_class = "flat", .icon = UI_ICON_GO_FORWARD);
- ui_path_textfield(obj, .varname = "path", .fill = UI_ON, .onactivate = action_pathbar_activate);
+ ui_path_textfield(obj, .varname = "path", .fill = TRUE, .onactivate = action_pathbar_activate);
}
window_create_browser_view(obj, wdata);
@@ -115,7 +120,7 @@ static void open_files(FileInfo **files, size_t numfiles, void *userdata) {
}
#ifdef GTK_MAJOR_VERSION
-static UIWIDGET create_filesview(UiObject *obj, UiWidgetArgs args, void *userdata) {
+static UIWIDGET create_filesview(UiObject *obj, UiWidgetArgs *args, void *userdata) {
MainWindow *win = userdata;
MzFilesView *view = mz_files_view_new();
view->open = open_files;
@@ -129,9 +134,9 @@ static UIWIDGET create_filesview(UiObject *obj, UiWidgetArgs args, void *userdat
#endif
void window_create_browser_view(UiObject *obj, MainWindow *win) {
- ui_tabview(obj, .tabview = UI_TABVIEW_INVISIBLE, .varname = "view") {
+ ui_tabview(obj, .tabview = UI_TABVIEW_INVISIBLE, .varname = "view", .fill = TRUE) {
ui_tab(obj, "iconview") {
- ui_customwidget(obj, create_filesview, win, .fill = UI_ON);
+ ui_customwidget(obj, create_filesview, win, .fill = TRUE);
}
ui_tab(obj, "listview") {
@@ -153,12 +158,12 @@ void windowdata_init(UiContext *ctx, MainWindow *win) {
*
* sublist_userdata: sublist identifier (sidebar_list_default_dirs, sidebar_list_user_dirs)
*/
-void window_sidebar_getvalue(void *sublist_userdata, void *rowdata, int index, UiSubListItem *item) {
+void window_sidebar_getvalue(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata) {
ui_sublist_getvalue_func getvalue = sublist_userdata;
- getvalue(NULL, rowdata, index, item);
+ getvalue(list ,NULL, rowdata, index, item, userdata);
}
-void window_sidebar_user_dirs_item(void *sublist_userdata, void *rowdata, int index, UiSubListItem *item) {
+void window_sidebar_user_dirs_item(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata) {
MZBookmark *bookmark = rowdata;
item->icon = strdup(bookmark->icon);
item->label = strdup(bookmark->name);
diff --git a/mizunara/window.h b/mizunara/window.h
index 3df9220..e3579c5 100644
--- a/mizunara/window.h
+++ b/mizunara/window.h
@@ -41,9 +41,9 @@ void window_create_browser_view(UiObject *obj, MainWindow *win);
void windowdata_init(UiContext *ctx, MainWindow *win);
-void window_sidebar_getvalue(void *sublist_userdata, void *rowdata, int index, UiSubListItem *item);
+void window_sidebar_getvalue(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata);
-void window_sidebar_user_dirs_item(void *sublist_userdata, void *rowdata, int index, UiSubListItem *item);
+void window_sidebar_user_dirs_item(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata);
void action_pathbar_activate(UiEvent *event, void *userdata);
diff --git a/ucx/Makefile b/ucx/Makefile
index e24476e..1005259 100644
--- a/ucx/Makefile
+++ b/ucx/Makefile
@@ -49,16 +49,20 @@ SRC += json.c
OBJ = $(SRC:%.c=../build/ucx/%$(OBJ_EXT))
-UCX_LIB = ../build/lib/libucx$(LIB_EXT)
+UCX_LIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)ucx$(LIB_EXT)
+UCX_SHLIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)ucx$(SHLIB_EXT)
-all: ../build/ucx $(UCX_LIB)
+all: $(UCX_LIB) $(UCX_SHLIB)
$(UCX_LIB): $(OBJ)
- $(AR) $(ARFLAGS) $(UCX_LIB) $(OBJ)
+ $(AR) $(ARFLAGS) $@ $(OBJ)
+
+$(UCX_SHLIB): $(OBJ)
+ $(CC) -o $@ $(LDFLAGS) $(SHLIB_LDFLAGS) $(OBJ)
../build/ucx:
mkdir -p ../build/ucx
../build/ucx/%$(OBJ_EXT): %.c
- $(CC) $(CFLAGS) -o $@ -c $<
+ $(CC) $(CFLAGS) $(SHLIB_CFLAGS) -o $@ -c $<
diff --git a/ucx/allocator.c b/ucx/allocator.c
index f6f20c8..b10096c 100644
--- a/ucx/allocator.c
+++ b/ucx/allocator.c
@@ -29,6 +29,7 @@
#include "cx/allocator.h"
#include
+#include
static void *cx_malloc_stdlib(
cx_attr_unused void *d,
@@ -60,18 +61,19 @@ static void cx_free_stdlib(
free(mem);
}
-static cx_allocator_class cx_default_allocator_class = {
+static cx_allocator_class cx_stdlib_allocator_class = {
cx_malloc_stdlib,
cx_realloc_stdlib,
cx_calloc_stdlib,
cx_free_stdlib
};
-struct cx_allocator_s cx_default_allocator = {
- &cx_default_allocator_class,
+struct cx_allocator_s cx_stdlib_allocator = {
+ &cx_stdlib_allocator_class,
NULL
};
-const CxAllocator * const cxDefaultAllocator = &cx_default_allocator;
+const CxAllocator * const cxStdlibAllocator = &cx_stdlib_allocator;
+const CxAllocator * cxDefaultAllocator = cxStdlibAllocator;
int cx_reallocate_(
void **mem,
@@ -115,6 +117,17 @@ void *cxMalloc(
return allocator->cl->malloc(allocator->data, n);
}
+void *cxZalloc(
+ const CxAllocator *allocator,
+ size_t n
+) {
+ void *mem = allocator->cl->malloc(allocator->data, n);
+ if (mem != NULL) {
+ memset(mem, 0, n);
+ }
+ return mem;
+}
+
void *cxRealloc(
const CxAllocator *allocator,
void *mem,
diff --git a/ucx/array_list.c b/ucx/array_list.c
index 5387bfb..a66db51 100644
--- a/ucx/array_list.c
+++ b/ucx/array_list.c
@@ -36,16 +36,17 @@
static void *cx_array_default_realloc(
void *array,
- size_t capacity,
+ cx_attr_unused size_t old_capacity,
+ size_t new_capacity,
size_t elem_size,
cx_attr_unused CxArrayReallocator *alloc
) {
size_t n;
- if (cx_szmul(capacity, elem_size, &n)) {
+ if (cx_szmul(new_capacity, elem_size, &n)) {
errno = EOVERFLOW;
return NULL;
}
- return realloc(array, n);
+ return cxReallocDefault(array, n);
}
CxArrayReallocator cx_array_default_reallocator_impl = {
@@ -58,13 +59,14 @@ CxArrayReallocator *cx_array_default_reallocator = &cx_array_default_reallocator
static void *cx_array_advanced_realloc(
void *array,
- size_t capacity,
+ size_t old_capacity,
+ size_t new_capacity,
size_t elem_size,
cx_attr_unused CxArrayReallocator *alloc
) {
// check for overflow
size_t n;
- if (cx_szmul(capacity, elem_size, &n)) {
+ if (cx_szmul(new_capacity, elem_size, &n)) {
errno = EOVERFLOW;
return NULL;
}
@@ -77,7 +79,7 @@ static void *cx_array_advanced_realloc(
if (array == alloc->ptr2) {
newmem = cxMalloc(al, n);
if (newmem != NULL && array != NULL) {
- memcpy(newmem, array, n);
+ memcpy(newmem, array, old_capacity*elem_size);
}
} else {
newmem = cxRealloc(al, array, n);
@@ -180,7 +182,7 @@ int cx_array_reserve(
// perform reallocation
void *newmem = reallocator->realloc(
- *array, newcap, elem_size, reallocator
+ *array, oldcap, newcap, elem_size, reallocator
);
if (newmem == NULL) {
return 1; // LCOV_EXCL_LINE
@@ -286,7 +288,7 @@ int cx_array_copy(
// perform reallocation
void *newmem = reallocator->realloc(
- *target, newcap, elem_size, reallocator
+ *target, oldcap, newcap, elem_size, reallocator
);
if (newmem == NULL) {
return 1;
@@ -366,13 +368,14 @@ int cx_array_insert_sorted(
// store some counts
size_t old_size = *size;
+ size_t old_capacity = *capacity;
size_t needed_capacity = old_size + elem_count;
// if we need more than we have, try a reallocation
- if (needed_capacity > *capacity) {
+ if (needed_capacity > old_capacity) {
size_t new_capacity = cx_array_align_capacity(needed_capacity, 16, SIZE_MAX);
void *new_mem = reallocator->realloc(
- *target, new_capacity, elem_size, reallocator
+ *target, old_capacity, new_capacity, elem_size, reallocator
);
if (new_mem == NULL) {
// give it up right away, there is no contract
@@ -572,7 +575,7 @@ void cx_array_swap(
// decide if we can use the local buffer
if (elem_size > CX_ARRAY_SWAP_SBO_SIZE) {
- tmp = malloc(elem_size);
+ tmp = cxMallocDefault(elem_size);
// we don't want to enforce error handling
if (tmp == NULL) abort();
} else {
@@ -591,7 +594,7 @@ void cx_array_swap(
// free dynamic memory, if it was needed
if (tmp != sbo_mem) {
- free(tmp);
+ cxFreeDefault(tmp);
}
}
@@ -638,50 +641,38 @@ static size_t cx_arl_insert_array(
// get a correctly typed pointer to the list
cx_array_list *arl = (cx_array_list *) list;
- // do we need to move some elements?
- if (index < list->collection.size) {
- const char *first_to_move = (const char *) arl->data;
- first_to_move += index * list->collection.elem_size;
- size_t elems_to_move = list->collection.size - index;
- size_t start_of_moved = index + n;
-
- if (cx_array_copy(
- &arl->data,
- &list->collection.size,
- &arl->capacity,
- 0,
- start_of_moved,
- first_to_move,
- list->collection.elem_size,
- elems_to_move,
- &arl->reallocator
- )) {
- // if moving existing elems is unsuccessful, abort
+ // guarantee enough capacity
+ if (arl->capacity < list->collection.size + n) {
+ size_t new_capacity = list->collection.size + n;
+ new_capacity = new_capacity - (new_capacity % 16) + 16;
+ if (cxReallocateArray(
+ list->collection.allocator,
+ &arl->data, new_capacity,
+ list->collection.elem_size)
+ ) {
return 0;
}
+ arl->capacity = new_capacity;
}
- // note that if we had to move the elements, the following operation
- // is guaranteed to succeed, because we have the memory already allocated
- // therefore, it is impossible to leave this function with an invalid array
+ // determine insert position
+ char *arl_data = arl->data;
+ char *insert_pos = arl_data + index * list->collection.elem_size;
- // place the new elements
- if (cx_array_copy(
- &arl->data,
- &list->collection.size,
- &arl->capacity,
- 0,
- index,
- array,
- list->collection.elem_size,
- n,
- &arl->reallocator
- )) {
- // array list implementation is "all or nothing"
- return 0;
- } else {
- return n;
+ // do we need to move some elements?
+ if (index < list->collection.size) {
+ size_t elems_to_move = list->collection.size - index;
+ char *target = insert_pos + n * list->collection.elem_size;
+ memmove(target, insert_pos, elems_to_move * list->collection.elem_size);
}
+
+ // place the new elements, if any
+ if (array != NULL) {
+ memcpy(insert_pos, array, n * list->collection.elem_size);
+ }
+ list->collection.size += n;
+
+ return n;
}
static size_t cx_arl_insert_sorted(
@@ -709,12 +700,16 @@ static size_t cx_arl_insert_sorted(
}
}
-static int cx_arl_insert_element(
+static void *cx_arl_insert_element(
struct cx_list_s *list,
size_t index,
const void *element
) {
- return 1 != cx_arl_insert_array(list, index, element, 1);
+ if (cx_arl_insert_array(list, index, element, 1) == 1) {
+ return ((char*)((cx_array_list *) list)->data) + index * list->collection.elem_size;
+ } else {
+ return NULL;
+ }
}
static int cx_arl_insert_iter(
@@ -724,26 +719,23 @@ static int cx_arl_insert_iter(
) {
struct cx_list_s *list = iter->src_handle.m;
if (iter->index < list->collection.size) {
- int result = cx_arl_insert_element(
- list,
- iter->index + 1 - prepend,
- elem
- );
- if (result == 0) {
- iter->elem_count++;
- if (prepend != 0) {
- iter->index++;
- iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size;
- }
+ if (cx_arl_insert_element(list,
+ iter->index + 1 - prepend, elem) == NULL) {
+ return 1;
+ }
+ iter->elem_count++;
+ if (prepend != 0) {
+ iter->index++;
+ iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size;
}
- return result;
+ return 0;
} else {
- int result = cx_arl_insert_element(list, list->collection.size, elem);
- if (result == 0) {
- iter->elem_count++;
- iter->index = list->collection.size;
+ if (cx_arl_insert_element(list, list->collection.size, elem) == NULL) {
+ return 1;
}
- return result;
+ iter->elem_count++;
+ iter->index = list->collection.size;
+ return 0;
}
}
diff --git a/ucx/buffer.c b/ucx/buffer.c
index 1a7713e..658dddf 100644
--- a/ucx/buffer.c
+++ b/ucx/buffer.c
@@ -32,6 +32,24 @@
#include
#include
+#ifdef _WIN32
+#include
+#include
+static unsigned long system_page_size() {
+ static unsigned long ps = 0;
+ if (ps == 0) {
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ ps = sysinfo.dwPageSize;
+ }
+ return ps;
+}
+#define SYSTEM_PAGE_SIZE system_page_size()
+#else
+#include
+#define SYSTEM_PAGE_SIZE sysconf(_SC_PAGESIZE)
+#endif
+
static int buffer_copy_on_write(CxBuffer* buffer) {
if (0 == (buffer->flags & CX_BUFFER_COPY_ON_WRITE)) return 0;
void *newspace = cxMalloc(buffer->allocator, buffer->capacity);
@@ -80,7 +98,7 @@ int cxBufferEnableFlushing(
CxBuffer *buffer,
CxBufferFlushConfig config
) {
- buffer->flush = malloc(sizeof(CxBufferFlushConfig));
+ buffer->flush = cxMallocDefault(sizeof(CxBufferFlushConfig));
if (buffer->flush == NULL) return -1; // LCOV_EXCL_LINE
memcpy(buffer->flush, &config, sizeof(CxBufferFlushConfig));
return 0;
@@ -90,7 +108,7 @@ void cxBufferDestroy(CxBuffer *buffer) {
if (buffer->flags & CX_BUFFER_FREE_CONTENTS) {
cxFree(buffer->allocator, buffer->bytes);
}
- free(buffer->flush);
+ cxFreeDefault(buffer->flush);
memset(buffer, 0, sizeof(CxBuffer));
}
@@ -139,6 +157,7 @@ int cxBufferSeek(
npos = 0;
break;
default:
+ errno = EINVAL;
return -1;
}
@@ -146,11 +165,16 @@ int cxBufferSeek(
npos += offset;
if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) {
- errno = EOVERFLOW;
+ // to be compliant with fseek() specification
+ // we return EINVAL on underflow
+ errno = EINVAL;
return -1;
}
if (npos > buffer->size) {
+ // not compliant with fseek() specification
+ // but this is the better behavior for CxBuffer
+ errno = EINVAL;
return -1;
} else {
buffer->pos = npos;
@@ -184,6 +208,28 @@ int cxBufferMinimumCapacity(
return 0;
}
+ unsigned long pagesize = SYSTEM_PAGE_SIZE;
+ // if page size is larger than 64 KB - for some reason - truncate to 64 KB
+ if (pagesize > 65536) pagesize = 65536;
+ if (newcap < pagesize) {
+ // when smaller as one page, map to the next power of two
+ newcap--;
+ newcap |= newcap >> 1;
+ newcap |= newcap >> 2;
+ newcap |= newcap >> 4;
+ // last operation only needed for pages larger 4096 bytes
+ // but if/else would be more expensive than just doing this
+ newcap |= newcap >> 8;
+ newcap++;
+ } else {
+ // otherwise, map to a multiple of the page size
+ newcap -= newcap % pagesize;
+ newcap += pagesize;
+ // note: if newcap is already page aligned,
+ // this gives a full additional page (which is good)
+ }
+
+
const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND;
if (buffer->flags & force_copy_flags) {
void *newspace = cxMalloc(buffer->allocator, newcap);
@@ -203,6 +249,28 @@ int cxBufferMinimumCapacity(
}
}
+void cxBufferShrink(
+ CxBuffer *buffer,
+ size_t reserve
+) {
+ // Ensure buffer is in a reallocatable state
+ const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND;
+ if (buffer->flags & force_copy_flags) {
+ // do nothing when we are not allowed to reallocate
+ return;
+ }
+
+ // calculate new capacity
+ size_t newCapacity = buffer->size + reserve;
+
+ // If new capacity is smaller than current capacity, resize the buffer
+ if (newCapacity < buffer->capacity) {
+ if (0 == cxReallocate(buffer->allocator, &buffer->bytes, newCapacity)) {
+ buffer->capacity = newCapacity;
+ }
+ }
+}
+
static size_t cx_buffer_flush_helper(
const CxBuffer *buffer,
const unsigned char *src,
@@ -399,10 +467,8 @@ int cxBufferPut(
}
int cxBufferTerminate(CxBuffer *buffer) {
- bool success = 0 == cxBufferPut(buffer, 0);
- if (success) {
- buffer->pos--;
- buffer->size--;
+ if (0 == cxBufferPut(buffer, 0)) {
+ buffer->size = buffer->pos - 1;
return 0;
} else {
return -1;
diff --git a/ucx/cx/allocator.h b/ucx/cx/allocator.h
index 8f16774..c169a92 100644
--- a/ucx/cx/allocator.h
+++ b/ucx/cx/allocator.h
@@ -98,10 +98,17 @@ struct cx_allocator_s {
typedef struct cx_allocator_s CxAllocator;
/**
- * A default allocator using standard library malloc() etc.
+ * A pre-defined allocator using standard library malloc() etc.
*/
cx_attr_export
-extern const CxAllocator * const cxDefaultAllocator;
+extern const CxAllocator * const cxStdlibAllocator;
+
+/**
+ * The default allocator that is used by UCX.
+ * Initialized with cxStdlibAllocator, but you may change it.
+ */
+cx_attr_export
+extern const CxAllocator * cxDefaultAllocator;
/**
* Function pointer type for destructor functions.
@@ -135,6 +142,8 @@ typedef void (*cx_destructor_func2)(
* Reallocate a previously allocated block and changes the pointer in-place,
* if necessary.
*
+ * @note This will use stdlib reallocate and @em not the cxDefaultAllocator.
+ *
* @par Error handling
* @c errno will be set by realloc() on failure.
*
@@ -158,6 +167,8 @@ int cx_reallocate_(
*
* The size is calculated by multiplying @p nemb and @p size.
*
+ * @note This will use stdlib reallocate and @em not the cxDefaultAllocator.
+ *
* @par Error handling
* @c errno will be set by realloc() on failure or when the multiplication of
* @p nmemb and @p size overflows.
@@ -182,6 +193,8 @@ int cx_reallocatearray_(
* Reallocate a previously allocated block and changes the pointer in-place,
* if necessary.
*
+ * @note This will use stdlib reallocate and @em not the cxDefaultAllocator.
+ *
* @par Error handling
* @c errno will be set by realloc() on failure.
*
@@ -199,6 +212,8 @@ int cx_reallocatearray_(
*
* The size is calculated by multiplying @p nemb and @p size.
*
+ * @note This will use stdlib reallocate and @em not the cxDefaultAllocator.
+ *
* @par Error handling
* @c errno will be set by realloc() on failure or when the multiplication of
* @p nmemb and @p size overflows.
@@ -212,6 +227,14 @@ int cx_reallocatearray_(
#define cx_reallocatearray(mem, nmemb, size) \
cx_reallocatearray_((void**)(mem), nmemb, size)
+/**
+ * Allocates memory and sets every byte to zero.
+ *
+ * @param n (@c size_t) the number of bytes
+ * @return (@c void*) a pointer to the allocated memory
+ */
+#define cx_zalloc(n) calloc(1, n)
+
/**
* Free a block allocated by this allocator.
*
@@ -414,6 +437,57 @@ void *cxCalloc(
size_t size
);
+/**
+ * Allocate @p n bytes of memory and sets every byte to zero.
+ *
+ * @param allocator the allocator
+ * @param n the number of bytes
+ * @return a pointer to the allocated memory
+ */
+cx_attr_nodiscard
+cx_attr_nonnull
+cx_attr_malloc
+cx_attr_dealloc_ucx
+cx_attr_allocsize(2)
+cx_attr_export
+void *cxZalloc(
+ const CxAllocator *allocator,
+ size_t n
+);
+
+/**
+ * Convenience macro that invokes cxMalloc() with the cxDefaultAllocator.
+ */
+#define cxMallocDefault(...) cxMalloc(cxDefaultAllocator, __VA_ARGS__)
+/**
+ * Convenience macro that invokes cxZalloc() with the cxDefaultAllocator.
+ */
+#define cxZallocDefault(...) cxZalloc(cxDefaultAllocator, __VA_ARGS__)
+/**
+ * Convenience macro that invokes cxCalloc() with the cxDefaultAllocator.
+ */
+#define cxCallocDefault(...) cxCalloc(cxDefaultAllocator, __VA_ARGS__)
+/**
+ * Convenience macro that invokes cxRealloc() with the cxDefaultAllocator.
+ */
+#define cxReallocDefault(...) cxRealloc(cxDefaultAllocator, __VA_ARGS__)
+/**
+ * Convenience macro that invokes cxReallocate() with the cxDefaultAllocator.
+ */
+#define cxReallocateDefault(...) cxReallocate(cxDefaultAllocator, __VA_ARGS__)
+/**
+ * Convenience macro that invokes cxReallocateArray() with the cxDefaultAllocator.
+ */
+#define cxReallocateArrayDefault(...) cxReallocateArray(cxDefaultAllocator, __VA_ARGS__)
+/**
+ * Convenience macro that invokes cxReallocArray() with the cxDefaultAllocator.
+ */
+#define cxReallocArrayDefault(...) cxReallocArray(cxDefaultAllocator, __VA_ARGS__)
+/**
+ * Convenience macro that invokes cxFree() with the cxDefaultAllocator.
+ */
+#define cxFreeDefault(...) cxFree(cxDefaultAllocator, __VA_ARGS__)
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/ucx/cx/array_list.h b/ucx/cx/array_list.h
index 198407f..b38710d 100644
--- a/ucx/cx/array_list.h
+++ b/ucx/cx/array_list.h
@@ -123,7 +123,8 @@ extern const unsigned cx_array_swap_sbo_size;
* @endcode
*
*
- * The memory for the array is allocated with stdlib malloc().
+ * The memory for the array is allocated with the cxDefaultAllocator.
+ *
* @param array the name of the array
* @param capacity the initial capacity
* @see cx_array_initialize_a()
@@ -133,7 +134,7 @@ extern const unsigned cx_array_swap_sbo_size;
#define cx_array_initialize(array, capacity) \
array##_capacity = capacity; \
array##_size = 0; \
- array = malloc(sizeof(array[0]) * capacity)
+ array = cxMallocDefault(sizeof(array[0]) * capacity)
/**
* Initializes an array with the given capacity using the specified allocator.
@@ -149,7 +150,6 @@ extern const unsigned cx_array_swap_sbo_size;
* cxFree(al, myarray); // don't forget to free with same allocator
* @endcode
*
- * The memory for the array is allocated with stdlib malloc().
* @param allocator (@c CxAllocator*) the allocator
* @param array the name of the array
* @param capacity the initial capacity
@@ -178,17 +178,19 @@ struct cx_array_reallocator_s {
* or to transport other additional data.
*
* @param array the array to reallocate
- * @param capacity the new capacity (number of elements)
+ * @param old_capacity the old number of elements
+ * @param new_capacity the new number of elements
* @param elem_size the size of each element
* @param alloc a reference to this allocator
* @return a pointer to the reallocated memory or @c NULL on failure
*/
cx_attr_nodiscard
- cx_attr_nonnull_arg(4)
- cx_attr_allocsize(2, 3)
+ cx_attr_nonnull_arg(5)
+ cx_attr_allocsize(3, 4)
void *(*realloc)(
void *array,
- size_t capacity,
+ size_t old_capacity,
+ size_t new_capacity,
size_t elem_size,
struct cx_array_reallocator_s *alloc
);
@@ -217,7 +219,7 @@ struct cx_array_reallocator_s {
typedef struct cx_array_reallocator_s CxArrayReallocator;
/**
- * A default stdlib-based array reallocator.
+ * A default array reallocator that is based on the cxDefaultAllocator.
*/
cx_attr_export
extern CxArrayReallocator *cx_array_default_reallocator;
@@ -225,7 +227,7 @@ extern CxArrayReallocator *cx_array_default_reallocator;
/**
* Creates a new array reallocator.
*
- * When @p allocator is @c NULL, the stdlib default allocator will be used.
+ * When @p allocator is @c NULL, the cxDefaultAllocator will be used.
*
* When @p stackmem is not @c NULL, the reallocator is supposed to be used
* @em only for the specific array that is initially located at @p stackmem.
@@ -699,7 +701,7 @@ void cx_array_swap(
* to cx_cmp_ptr(), if none is given.
*
* @param allocator the allocator for allocating the list memory
- * (if @c NULL, a default stdlib allocator will be used)
+ * (if @c NULL, the cxDefaultAllocator will be used)
* @param comparator the comparator for the elements
* (if @c NULL, and the list is not storing pointers, sort and find
* functions will not work)
@@ -727,7 +729,7 @@ CxList *cxArrayListCreate(
*
* If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
* copies of the added elements and the compare function will be automatically set
- * to cx_cmp_ptr(), if none is given.
+ * to cx_cmp_ptr().
*
* @param elem_size (@c size_t) the size of each element in bytes
* @param initial_capacity (@c size_t) the initial number of elements the array can store
diff --git a/ucx/cx/buffer.h b/ucx/cx/buffer.h
index e286832..867fb30 100644
--- a/ucx/cx/buffer.h
+++ b/ucx/cx/buffer.h
@@ -222,7 +222,7 @@ typedef struct cx_buffer_s CxBuffer;
* @param capacity the capacity of the buffer
* @param allocator the allocator this buffer shall use for automatic
* memory management
- * (if @c NULL, a default stdlib allocator will be used)
+ * (if @c NULL, the cxDefaultAllocator will be used)
* @param flags buffer features (see cx_buffer_s.flags)
* @return zero on success, non-zero if a required allocation failed
*/
@@ -305,7 +305,7 @@ void cxBufferFree(CxBuffer *buffer);
* @param capacity the capacity of the buffer
* @param allocator the allocator to use for allocating the structure and the automatic
* memory management within the buffer
- * (if @c NULL, a default stdlib allocator will be used)
+ * (if @c NULL, the cxDefaultAllocator will be used)
* @param flags buffer features (see cx_buffer_s.flags)
* @return a pointer to the buffer on success, @c NULL if a required allocation failed
*/
@@ -474,10 +474,14 @@ bool cxBufferEof(const CxBuffer *buffer);
*
* If the current capacity is not sufficient, the buffer will be extended.
*
+ * The new capacity will be a power of two until the system's page size is reached.
+ * Then, the new capacity will be a multiple of the page size.
+ *
* @param buffer the buffer
* @param capacity the minimum required capacity for this buffer
* @retval zero the capacity was already sufficient or successfully increased
* @retval non-zero on allocation failure
+ * @see cxBufferShrink()
*/
cx_attr_nonnull
cx_attr_export
@@ -486,6 +490,29 @@ int cxBufferMinimumCapacity(
size_t capacity
);
+/**
+ * Shrinks the capacity of the buffer to fit its current size.
+ *
+ * If @p reserve is larger than zero, the buffer is shrunk to its size plus
+ * the number of reserved bytes.
+ *
+ * If the current capacity is not larger than the size plus the reserved bytes,
+ * nothing happens.
+ *
+ * If the #CX_BUFFER_COPY_ON_WRITE or #CX_BUFFER_COPY_ON_EXTEND flag is set,
+ * this function does nothing.
+ *
+ * @param buffer the buffer
+ * @param reserve the number of bytes that shall remain reserved
+ * @see cxBufferMinimumCapacity()
+ */
+cx_attr_nonnull
+cx_attr_export
+void cxBufferShrink(
+ CxBuffer *buffer,
+ size_t reserve
+);
+
/**
* Writes data to a CxBuffer.
*
@@ -674,11 +701,10 @@ int cxBufferPut(
/**
* Writes a terminating zero to a buffer at the current position.
*
- * On successful write, @em neither the position @em nor the size of the buffer is
- * increased.
+ * If successful, sets the size to the current position and advances the position by one.
*
* The purpose of this function is to have the written data ready to be used as
- * a C string.
+ * a C string with the buffer's size being the length of that string.
*
* @param buffer the buffer to write to
* @return zero, if the terminator could be written, non-zero otherwise
diff --git a/ucx/cx/common.h b/ucx/cx/common.h
index 604ca5f..0fc9e47 100644
--- a/ucx/cx/common.h
+++ b/ucx/cx/common.h
@@ -46,7 +46,7 @@
* Repositories:
* https://sourceforge.net/p/ucx/code
* - or -
- * https://develop.uap-core.de/hg/ucx
+ * https://uap-core.de/hg/ucx
*
*
* LICENCE
@@ -150,7 +150,7 @@
*/
#define cx_attr_malloc __attribute__((__malloc__))
-#ifndef __clang__
+#if !defined(__clang__) && __GNUC__ >= 11
/**
* The pointer returned by the attributed function is supposed to be freed
* by @p freefunc.
@@ -240,20 +240,6 @@
*/
#define cx_attr_access_w(...) cx_attr_access(__write_only__, __VA_ARGS__)
-#if __STDC_VERSION__ >= 202300L
-
-/**
- * Do not warn about unused variable.
- */
-#define cx_attr_unused [[maybe_unused]]
-
-/**
- * Warn about discarded return value.
- */
-#define cx_attr_nodiscard [[nodiscard]]
-
-#else // no C23
-
/**
* Do not warn about unused variable.
*/
@@ -264,8 +250,6 @@
*/
#define cx_attr_nodiscard __attribute__((__warn_unused_result__))
-#endif // __STDC_VERSION__
-
// ---------------------------------------------------------------------------
// MSVC specifics
diff --git a/ucx/cx/hash_map.h b/ucx/cx/hash_map.h
index 07e1155..6b11e2c 100644
--- a/ucx/cx/hash_map.h
+++ b/ucx/cx/hash_map.h
@@ -77,7 +77,7 @@ struct cx_hash_map_s {
* In other words, when the iterator is finished, @c index==size .
*
* @param allocator the allocator to use
- * (if @c NULL, a default stdlib allocator will be used)
+ * (if @c NULL, the cxDefaultAllocator will be used)
* @param itemsize the size of one element
* @param buckets the initial number of buckets in this hash map
* @return a pointer to the new hash map
diff --git a/ucx/cx/linked_list.h b/ucx/cx/linked_list.h
index fcdae74..3da2cae 100644
--- a/ucx/cx/linked_list.h
+++ b/ucx/cx/linked_list.h
@@ -51,7 +51,7 @@ extern "C" {
* to cx_cmp_ptr(), if none is given.
*
* @param allocator the allocator for allocating the list nodes
- * (if @c NULL, a default stdlib allocator will be used)
+ * (if @c NULL, the cxDefaultAllocator will be used)
* @param comparator the comparator for the elements
* (if @c NULL, and the list is not storing pointers, sort and find
* functions will not work)
@@ -77,7 +77,7 @@ CxList *cxLinkedListCreate(
*
* If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of
* copies of the added elements and the compare function will be automatically set
- * to cx_cmp_ptr(), if none is given.
+ * to cx_cmp_ptr().
*
* @param elem_size (@c size_t) the size of each element in bytes
* @return (@c CxList*) the created list
@@ -393,7 +393,7 @@ void cx_linked_list_insert_sorted_chain(
* @li @p loc_next and @p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance)
* @li @p loc_next and @p begin (ancestor node is determined by list traversal, overall O(n) performance)
*
- * @remark The @c next and @c prev pointers of the removed node are not cleared by this function and may still be used
+ * @remark The @c next and @c prev pointers of the removed chain are not cleared by this function and may still be used
* to traverse to a former adjacent node in the list, or within the chain.
*
* @param begin a pointer to the beginning node pointer (optional)
diff --git a/ucx/cx/list.h b/ucx/cx/list.h
index 2df6c50..14ddc04 100644
--- a/ucx/cx/list.h
+++ b/ucx/cx/list.h
@@ -80,8 +80,10 @@ struct cx_list_class_s {
/**
* Member function for inserting a single element.
+ * The data pointer may be @c NULL in which case the function shall only allocate memory.
+ * Returns a pointer to the data of the inserted element.
*/
- int (*insert_element)(
+ void *(*insert_element)(
struct cx_list_s *list,
size_t index,
const void *data
@@ -202,6 +204,22 @@ struct cx_list_class_s {
);
};
+/**
+ * Common type for all list implementations.
+ */
+typedef struct cx_list_s CxList;
+
+/**
+ * A shared instance of an empty list.
+ *
+ * Writing to that list is not allowed.
+ *
+ * You can use this is a placeholder for initializing CxList pointers
+ * for which you do not want to reserve memory right from the beginning.
+ */
+cx_attr_export
+extern CxList *const cxEmptyList;
+
/**
* Default implementation of an array insert.
*
@@ -335,11 +353,6 @@ void cx_list_init(
size_t elem_size
);
-/**
- * Common type for all list implementations.
- */
-typedef struct cx_list_s CxList;
-
/**
* Returns the number of elements currently stored in the list.
*
@@ -359,6 +372,7 @@ static inline size_t cxListSize(const CxList *list) {
* @retval zero success
* @retval non-zero memory allocation failure
* @see cxListAddArray()
+ * @see cxListEmplace()
*/
cx_attr_nonnull
static inline int cxListAdd(
@@ -366,7 +380,7 @@ static inline int cxListAdd(
const void *elem
) {
list->collection.sorted = false;
- return list->cl->insert_element(list, list->collection.size, elem);
+ return list->cl->insert_element(list, list->collection.size, elem) == NULL;
}
/**
@@ -407,6 +421,7 @@ static inline size_t cxListAddArray(
* @retval non-zero memory allocation failure or the index is out of bounds
* @see cxListInsertAfter()
* @see cxListInsertBefore()
+ * @see cxListEmplaceAt()
*/
cx_attr_nonnull
static inline int cxListInsert(
@@ -415,7 +430,41 @@ static inline int cxListInsert(
const void *elem
) {
list->collection.sorted = false;
- return list->cl->insert_element(list, index, elem);
+ return list->cl->insert_element(list, index, elem) == NULL;
+}
+
+/**
+ * Allocates memory for an element at the specified index and returns a pointer to that memory.
+ *
+ * @remark When the list is storing pointers, this will return a @c void**.
+ *
+ * @param list the list
+ * @param index the index where to emplace the element
+ * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds
+ * @see cxListEmplace()
+ * @see cxListInsert()
+ */
+cx_attr_nonnull
+static inline void *cxListEmplaceAt(CxList *list, size_t index) {
+ list->collection.sorted = false;
+ return list->cl->insert_element(list, index, NULL);
+}
+
+
+/**
+ * Allocates memory for an element at the end of the list and returns a pointer to that memory.
+ *
+ * @remark When the list is storing pointers, this will return a @c void**.
+ *
+ * @param list the list
+ * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds
+ * @see cxListEmplaceAt()
+ * @see cxListAdd()
+ */
+cx_attr_nonnull
+static inline void *cxListEmplace(CxList *list) {
+ list->collection.sorted = false;
+ return list->cl->insert_element(list, list->collection.size, NULL);
}
/**
@@ -571,8 +620,9 @@ static inline int cxListRemove(
/**
* Removes and returns the element at the specified index.
*
- * No destructor is called and instead the element is copied to the
+ * No destructor is called, and instead the element is copied to the
* @p targetbuf which MUST be large enough to hold the removed element.
+ * If the list is storing pointers, only the pointer is copied to @p targetbuf.
*
* @param list the list
* @param index the index of the element
@@ -590,12 +640,94 @@ static inline int cxListRemoveAndGet(
return list->cl->remove(list, index, 1, targetbuf) == 0;
}
+/**
+ * Removes and returns the first element of the list.
+ *
+ * No destructor is called, and instead the element is copied to the
+ * @p targetbuf which MUST be large enough to hold the removed element.
+ * If the list is storing pointers, only the pointer is copied to @p targetbuf.
+ *
+ * @param list the list
+ * @param targetbuf a buffer where to copy the element
+ * @retval zero success
+ * @retval non-zero list is empty
+ * @see cxListPopFront()
+ * @see cxListRemoveAndGetLast()
+ */
+cx_attr_nonnull
+cx_attr_access_w(2)
+static inline int cxListRemoveAndGetFirst(
+ CxList *list,
+ void *targetbuf
+) {
+ return list->cl->remove(list, 0, 1, targetbuf) == 0;
+}
+
+/**
+ * Removes and returns the first element of the list.
+ *
+ * Alias for cxListRemoveAndGetFirst().
+ *
+ * No destructor is called, and instead the element is copied to the
+ * @p targetbuf which MUST be large enough to hold the removed element.
+ * If the list is storing pointers, only the pointer is copied to @p targetbuf.
+ *
+ * @param list (@c CxList*) the list
+ * @param targetbuf (@c void*) a buffer where to copy the element
+ * @retval zero success
+ * @retval non-zero list is empty
+ * @see cxListRemoveAndGetFirst()
+ * @see cxListPop()
+ */
+#define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf))
+
+
+/**
+ * Removes and returns the last element of the list.
+ *
+ * No destructor is called, and instead the element is copied to the
+ * @p targetbuf which MUST be large enough to hold the removed element.
+ * If the list is storing pointers, only the pointer is copied to @p targetbuf.
+ *
+ * @param list the list
+ * @param targetbuf a buffer where to copy the element
+ * @retval zero success
+ * @retval non-zero list is empty
+ */
+cx_attr_nonnull
+cx_attr_access_w(2)
+static inline int cxListRemoveAndGetLast(
+ CxList *list,
+ void *targetbuf
+) {
+ // note: index may wrap - member function will catch that
+ return list->cl->remove(list, list->collection.size - 1, 1, targetbuf) == 0;
+}
+
+/**
+ * Removes and returns the last element of the list.
+ *
+ * Alias for cxListRemoveAndGetLast().
+ *
+ * No destructor is called, and instead the element is copied to the
+ * @p targetbuf which MUST be large enough to hold the removed element.
+ * If the list is storing pointers, only the pointer is copied to @p targetbuf.
+ *
+ * @param list (@c CxList*) the list
+ * @param targetbuf (@c void*) a buffer where to copy the element
+ * @retval zero success
+ * @retval non-zero list is empty
+ * @see cxListRemoveAndGetLast()
+ * @see cxListPopFront()
+ */
+#define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf))
+
/**
* Removes multiple element starting at the specified index.
*
* If an element destructor function is specified, it is called for each
* element. It is guaranteed that the destructor is called before removing
- * the element, however, due to possible optimizations it is neither guaranteed
+ * the element. However, due to possible optimizations, it is neither guaranteed
* that the destructors are invoked for all elements before starting to remove
* them, nor that the element is removed immediately after the destructor call
* before proceeding to the next element.
@@ -615,10 +747,11 @@ static inline size_t cxListRemoveArray(
}
/**
- * Removes and returns multiple element starting at the specified index.
+ * Removes and returns multiple elements starting at the specified index.
*
- * No destructor is called and instead the elements are copied to the
+ * No destructor is called, and instead the elements are copied to the
* @p targetbuf which MUST be large enough to hold all removed elements.
+ * If the list is storing pointers, @p targetbuf is expected to be an array of pointers.
*
* @param list the list
* @param index the index of the element
@@ -654,15 +787,15 @@ static inline void cxListClear(CxList *list) {
/**
* Swaps two items in the list.
*
- * Implementations should only allocate temporary memory for the swap, if
+ * Implementations should only allocate temporary memory for the swap if
* it is necessary.
*
* @param list the list
* @param i the index of the first element
* @param j the index of the second element
* @retval zero success
- * @retval non-zero one of the indices is out of bounds
- * or the swap needed extra memory but allocation failed
+ * @retval non-zero one of the indices is out of bounds,
+ * or the swap needed extra memory, but allocation failed
*/
cx_attr_nonnull
static inline int cxListSwap(
@@ -677,6 +810,8 @@ static inline int cxListSwap(
/**
* Returns a pointer to the element at the specified index.
*
+ * If the list is storing pointers, returns the pointer stored at the specified index.
+ *
* @param list the list
* @param index the index of the element
* @return a pointer to the element or @c NULL if the index is out of bounds
@@ -689,6 +824,49 @@ static inline void *cxListAt(
return list->cl->at(list, index);
}
+/**
+ * Returns a pointer to the first element.
+ *
+ * If the list is storing pointers, returns the first pointer stored in the list.
+ *
+ * @param list the list
+ * @return a pointer to the first element or @c NULL if the list is empty
+ */
+cx_attr_nonnull
+static inline void *cxListFirst(const CxList *list) {
+ return list->cl->at(list, 0);
+}
+
+/**
+ * Returns a pointer to the last element.
+ *
+ * If the list is storing pointers, returns the last pointer stored in the list.
+ *
+ * @param list the list
+ * @return a pointer to the last element or @c NULL if the list is empty
+ */
+cx_attr_nonnull
+static inline void *cxListLast(const CxList *list) {
+ return list->cl->at(list, list->collection.size - 1);
+}
+
+/**
+ * Sets the element at the specified index in the list
+ *
+ * @param list the list to set the element in
+ * @param index the index to set the element at
+ * @param elem element to set
+ * @retval zero on success
+ * @retval non-zero when index is out of bounds
+ */
+cx_attr_nonnull
+cx_attr_export
+int cxListSet(
+ CxList *list,
+ size_t index,
+ const void *elem
+);
+
/**
* Returns an iterator pointing to the item at the specified index.
*
@@ -773,14 +951,14 @@ CxIterator cxListMutBackwardsIteratorAt(
*
* The returned iterator is position-aware.
*
- * If the list is empty, a past-the-end iterator will be returned.
+ * If the list is empty or @c NULL, a past-the-end iterator will be returned.
*
* @param list the list
* @return a new iterator
*/
-cx_attr_nonnull
cx_attr_nodiscard
static inline CxIterator cxListIterator(const CxList *list) {
+ if (list == NULL) list = cxEmptyList;
return list->cl->iterator(list, 0, false);
}
@@ -789,14 +967,14 @@ static inline CxIterator cxListIterator(const CxList *list) {
*
* The returned iterator is position-aware.
*
- * If the list is empty, a past-the-end iterator will be returned.
+ * If the list is empty or @c NULL, a past-the-end iterator will be returned.
*
* @param list the list
* @return a new iterator
*/
-cx_attr_nonnull
cx_attr_nodiscard
static inline CxIterator cxListMutIterator(CxList *list) {
+ if (list == NULL) list = cxEmptyList;
return cxListMutIteratorAt(list, 0);
}
@@ -806,14 +984,14 @@ static inline CxIterator cxListMutIterator(CxList *list) {
*
* The returned iterator is position-aware.
*
- * If the list is empty, a past-the-end iterator will be returned.
+ * If the list is empty or @c NULL, a past-the-end iterator will be returned.
*
* @param list the list
* @return a new iterator
*/
-cx_attr_nonnull
cx_attr_nodiscard
static inline CxIterator cxListBackwardsIterator(const CxList *list) {
+ if (list == NULL) list = cxEmptyList;
return list->cl->iterator(list, list->collection.size - 1, true);
}
@@ -822,14 +1000,14 @@ static inline CxIterator cxListBackwardsIterator(const CxList *list) {
*
* The returned iterator is position-aware.
*
- * If the list is empty, a past-the-end iterator will be returned.
+ * If the list is empty or @c NULL, a past-the-end iterator will be returned.
*
* @param list the list
* @return a new iterator
*/
-cx_attr_nonnull
cx_attr_nodiscard
static inline CxIterator cxListMutBackwardsIterator(CxList *list) {
+ if (list == NULL) list = cxEmptyList;
return cxListMutBackwardsIteratorAt(list, list->collection.size - 1);
}
@@ -842,6 +1020,7 @@ static inline CxIterator cxListMutBackwardsIterator(CxList *list) {
* @param elem the element to find
* @return the index of the element or the size of the list when the element is not found
* @see cxListIndexValid()
+ * @see cxListContains()
*/
cx_attr_nonnull
cx_attr_nodiscard
@@ -852,6 +1031,26 @@ static inline size_t cxListFind(
return list->cl->find_remove((CxList*)list, elem, false);
}
+/**
+ * Checks, if the list contains the specified element.
+ *
+ * The elements are compared with the list's comparator function.
+ *
+ * @param list the list
+ * @param elem the element to find
+ * @retval true if the element is contained
+ * @retval false if the element is not contained
+ * @see cxListFind()
+ */
+cx_attr_nonnull
+cx_attr_nodiscard
+static inline bool cxListContains(
+ const CxList* list,
+ const void* elem
+) {
+ return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size;
+}
+
/**
* Checks if the specified index is within bounds.
*
@@ -894,6 +1093,7 @@ static inline size_t cxListFindRemove(
*/
cx_attr_nonnull
static inline void cxListSort(CxList *list) {
+ if (list->collection.sorted) return;
list->cl->sort(list);
list->collection.sorted = true;
}
@@ -942,17 +1142,6 @@ int cxListCompare(
cx_attr_export
void cxListFree(CxList *list);
-/**
- * A shared instance of an empty list.
- *
- * Writing to that list is not allowed.
- *
- * You can use this is a placeholder for initializing CxList pointers
- * for which you do not want to reserve memory right from the beginning.
- */
-cx_attr_export
-extern CxList *const cxEmptyList;
-
#ifdef __cplusplus
} // extern "C"
diff --git a/ucx/cx/mempool.h b/ucx/cx/mempool.h
index 43b3b17..5d8d284 100644
--- a/ucx/cx/mempool.h
+++ b/ucx/cx/mempool.h
@@ -43,31 +43,107 @@
extern "C" {
#endif
-/** Internal structure for pooled memory. */
-struct cx_mempool_memory_s;
+/** A memory block in a simple memory pool. */
+struct cx_mempool_memory_s {
+ /** The destructor. */
+ cx_destructor_func destructor;
+ /** The actual memory. */
+ char c[];
+};
+
+/** A memory block in an advanced memory pool. */
+struct cx_mempool_memory2_s {
+ /** The destructor. */
+ cx_destructor_func2 destructor;
+ /** Data for the destructor. */
+ void *data;
+ /** The actual memory. */
+ char c[];
+};
+
+/** Represents memory that is not allocated by, but registered with a pool. */
+struct cx_mempool_foreign_memory_s {
+ /** The foreign memory. */
+ void* mem;
+ union {
+ /** Simple destructor. */
+ cx_destructor_func destr;
+ /** Advanced destructor. */
+ cx_destructor_func2 destr2;
+ };
+ /** Data for the advanced destructor. */
+ void *destr2_data;
+};
+
+/** Specifies how individual blocks are allocated. */
+enum cx_mempool_type {
+ /**
+ * Allows registration of cx_destructor_func for each memory block.
+ */
+ CX_MEMPOOL_TYPE_SIMPLE,
+ /**
+ * Allows registration of cx_destructor_func2 for each memory block.
+ */
+ CX_MEMPOOL_TYPE_ADVANCED,
+ /**
+ * No individual destructor registration allowed.
+ *
+ * In this mode, no additional memory per block is allocated.
+ */
+ CX_MEMPOOL_TYPE_PURE,
+};
/**
* The basic structure of a memory pool.
* Should be the first member of an actual memory pool implementation.
*/
struct cx_mempool_s {
+ /** The used allocator, initialized with the cxDefaultAllocator. */
+ const CxAllocator * const base_allocator;
+
/** The provided allocator. */
const CxAllocator *allocator;
- /**
- * A destructor that shall be automatically registered for newly allocated memory.
- * This destructor MUST NOT free the memory.
- */
- cx_destructor_func auto_destr;
-
/** Array of pooled memory. */
- struct cx_mempool_memory_s **data;
+ void **data;
/** Number of pooled memory items. */
size_t size;
/** Memory pool capacity. */
size_t capacity;
+
+ /** Array of registered memory. */
+ struct cx_mempool_foreign_memory_s *registered;
+
+ /** Number of registered memory items. */
+ size_t registered_size;
+
+ /** Capacity for registered memory. */
+ size_t registered_capacity;
+
+ /**
+ * A destructor that shall be called before deallocating a memory block.
+ * This destructor MUST NOT free the memory itself.
+ *
+ * It is guaranteed that this destructor is called after the individual
+ * destructor of the memory block and before @c destr2.
+ */
+ cx_destructor_func destr;
+
+ /**
+ * A destructor that shall be called before deallocating a memory block.
+ * This destructor MUST NOT free the memory itself.
+ *
+ * It is guaranteed that this destructor is called after the individual
+ * destructor of the memory block and @c destr.
+ */
+ cx_destructor_func2 destr2;
+
+ /**
+ * Additional data for the @c destr2.
+ */
+ void *destr2_data;
};
/**
@@ -84,31 +160,76 @@ cx_attr_export
void cxMempoolFree(CxMempool *pool);
/**
- * Creates an array-based memory pool with a shared destructor function.
+ * Creates an array-based memory pool.
*
- * This destructor MUST NOT free the memory.
+ * The type determines how much additional memory is allocated per block
+ * to register a destructor function.
*
- * @param capacity the initial capacity of the pool
- * @param destr optional destructor function to use for allocated memory
+ * @param capacity the initial capacity of the pool (an implementation default if zero)
+ * @param type the type of memory pool
* @return the created memory pool or @c NULL if allocation failed
*/
cx_attr_nodiscard
cx_attr_malloc
cx_attr_dealloc(cxMempoolFree, 1)
cx_attr_export
-CxMempool *cxMempoolCreate(size_t capacity, cx_destructor_func destr);
+CxMempool *cxMempoolCreate(size_t capacity, enum cx_mempool_type type);
/**
* Creates a basic array-based memory pool.
*
+ * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_SIMPLE.
+ *
* @param capacity (@c size_t) the initial capacity of the pool
* @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed
*/
-#define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, NULL)
+#define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_SIMPLE)
+
+/**
+ * Creates a basic array-based memory pool.
+ *
+ * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_ADVANCED.
+ *
+ * @param capacity (@c size_t) the initial capacity of the pool
+ * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed
+ */
+#define cxMempoolCreateAdvanced(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_ADVANCED)
+
+/**
+ * Creates a basic array-based memory pool.
+ *
+ * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_PURE.
+ *
+ * @param capacity (@c size_t) the initial capacity of the pool
+ * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed
+ */
+#define cxMempoolCreatePure(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_PURE)
+
+/**
+ * Sets the global destructor for all memory blocks within the specified pool.
+ *
+ * @param pool the memory pool
+ * @param fnc the destructor that shall be applied to all memory blocks
+ */
+cx_attr_nonnull_arg(1)
+cx_attr_export
+void cxMempoolGlobalDestructor(CxMempool *pool, cx_destructor_func fnc);
+
+/**
+ * Sets the global destructor for all memory blocks within the specified pool.
+ *
+ * @param pool the memory pool
+ * @param fnc the destructor that shall be applied to all memory blocks
+ * @param data additional data for the destructor function
+ */
+cx_attr_nonnull_arg(1)
+cx_attr_export
+void cxMempoolGlobalDestructor2(CxMempool *pool, cx_destructor_func2 fnc, void *data);
/**
* Sets the destructor function for a specific allocated memory object.
*
+ * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined.
* If the memory is not managed by a UCX memory pool, the behavior is undefined.
* The destructor MUST NOT free the memory.
*
@@ -123,24 +244,56 @@ void cxMempoolSetDestructor(
);
/**
- * Removes the destructor function for a specific allocated memory object.
+ * Sets the destructor function for a specific allocated memory object.
*
+ * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined.
* If the memory is not managed by a UCX memory pool, the behavior is undefined.
* The destructor MUST NOT free the memory.
*
* @param memory the object allocated in the pool
+ * @param fnc the destructor function
+ * @param data additional data for the destructor function
+ */
+cx_attr_nonnull
+cx_attr_export
+void cxMempoolSetDestructor2(
+ void *memory,
+ cx_destructor_func2 fnc,
+ void *data
+);
+
+/**
+ * Removes the destructor function for a specific allocated memory object.
+ *
+ * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined.
+ * If the memory is not managed by a UCX memory pool, the behavior is undefined.
+ *
+ * @param memory the object allocated in the pool
*/
cx_attr_nonnull
cx_attr_export
void cxMempoolRemoveDestructor(void *memory);
+/**
+ * Removes the destructor function for a specific allocated memory object.
+ *
+ * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined.
+ * If the memory is not managed by a UCX memory pool, the behavior is undefined.
+ *
+ * @param memory the object allocated in the pool
+ */
+cx_attr_nonnull
+cx_attr_export
+void cxMempoolRemoveDestructor2(void *memory);
+
/**
* Registers foreign memory with this pool.
*
* The destructor, in contrast to memory allocated by the pool, MUST free the memory.
+ * This function can be used with any pool of any type, since destructors for registered memory
+ * are entirely independent of the pool's memory management.
*
- * A small portion of memory will be allocated to register the information in the pool.
- * If that allocation fails, this function will return non-zero.
+ * The destructor for the registered memory will be called after all pooled items have been freed.
*
* @param pool the pool
* @param memory the object to register (MUST NOT be already allocated in the pool)
@@ -156,6 +309,79 @@ int cxMempoolRegister(
cx_destructor_func destr
);
+
+/**
+ * Registers foreign memory with this pool.
+ *
+ * The destructor, in contrast to memory allocated by the pool, MUST free the memory.
+ * This function can be used with any pool of any type, since destructors for registered memory
+ * are entirely independent of the pool's memory management.
+ *
+ * The destructor for the registered memory will be called after all pooled items have been freed.
+ *
+ * @attention The data pointer MUST NOT be @c NULL.
+ * If you wish to register a destructor without additional data, use cxMempoolRegister().
+ *
+ * @param pool the pool
+ * @param memory the object to register (MUST NOT be already allocated in the pool)
+ * @param destr the destructor function
+ * @param data additional data for the destructor function
+ * @retval zero success
+ * @retval non-zero failure
+ */
+cx_attr_nonnull
+cx_attr_export
+int cxMempoolRegister2(
+ CxMempool *pool,
+ void *memory,
+ cx_destructor_func2 destr,
+ void *data
+);
+
+/**
+ * Transfers all the memory managed by one pool to another.
+ *
+ * The allocator of the source pool will also be transferred and registered with the destination pool
+ * and stays valid, as long as the destination pool is not destroyed.
+ *
+ * The source pool will get a completely new allocator and can be reused or destroyed afterward.
+ *
+ * This function fails when the destination pool has a different type than the source pool.
+ *
+ * @param source the pool to move the memory from
+ * @param dest the pool where to transfer the memory to
+ * @retval zero success
+ * @retval non-zero allocation failure or incompatible pools
+ */
+cx_attr_nonnull
+cx_attr_export
+int cxMempoolTransfer(
+ CxMempool *source,
+ CxMempool *dest
+);
+
+/**
+ * Transfers an object from one pool to another.
+ *
+ * This function fails when the destination pool has a different type than the source pool.
+ *
+ * @attention If the object maintains a reference to the pool's allocator,
+ * you must make sure to update that reference to the allocator of the destination pool.
+ *
+ * @param source the pool to move the memory from
+ * @param dest the pool where to transfer the memory to
+ * @param obj pointer to the object that shall be transferred
+ * @retval zero success
+ * @retval non-zero failure, or the object was not found in the source pool, or the pools are incompatible
+ */
+cx_attr_nonnull
+cx_attr_export
+int cxMempoolTransferObject(
+ CxMempool *source,
+ CxMempool *dest,
+ const void *obj
+);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/ucx/cx/printf.h b/ucx/cx/printf.h
index f02a80f..4ffd05f 100644
--- a/ucx/cx/printf.h
+++ b/ucx/cx/printf.h
@@ -229,7 +229,7 @@ cx_attr_printf(4, 5)
cx_attr_cstr_arg(4)
cx_attr_export
int cx_sprintf_a(
- CxAllocator *alloc,
+ const CxAllocator *alloc,
char **str,
size_t *len,
const char *fmt,
@@ -274,7 +274,7 @@ cx_attr_access_rw(2)
cx_attr_access_rw(3)
cx_attr_export
int cx_vsprintf_a(
- CxAllocator *alloc,
+ const CxAllocator *alloc,
char **str,
size_t *len,
const char *fmt,
@@ -333,7 +333,7 @@ cx_attr_access_rw(3)
cx_attr_access_rw(4)
cx_attr_export
int cx_sprintf_sa(
- CxAllocator *alloc,
+ const CxAllocator *alloc,
char *buf,
size_t *len,
char **str,
@@ -388,7 +388,7 @@ cx_attr_nonnull
cx_attr_cstr_arg(5)
cx_attr_export
int cx_vsprintf_sa(
- CxAllocator *alloc,
+ const CxAllocator *alloc,
char *buf,
size_t *len,
char **str,
diff --git a/ucx/cx/properties.h b/ucx/cx/properties.h
index 619229f..d6df8f5 100644
--- a/ucx/cx/properties.h
+++ b/ucx/cx/properties.h
@@ -551,10 +551,12 @@ CxPropertiesStatus cxPropertiesNext(
/**
* Creates a properties sink for an UCX map.
*
- * The values stored in the map will be pointers to strings allocated
- * by #cx_strdup_a().
- * The default stdlib allocator will be used, unless you specify a custom
- * allocator in the optional @c data of the sink.
+ * The values stored in the map will be pointers to freshly allocated,
+ * zero-terminated C strings (@c char*), which means the @p map should have been
+ * created with #CX_STORE_POINTERS.
+ *
+ * The cxDefaultAllocator will be used unless you specify a custom
+ * allocator in the optional @c data field of the returned sink.
*
* @param map the map that shall consume the k/v-pairs.
* @return the sink
diff --git a/ucx/cx/string.h b/ucx/cx/string.h
index 64c8dba..41bf18a 100644
--- a/ucx/cx/string.h
+++ b/ucx/cx/string.h
@@ -39,6 +39,12 @@
#include "common.h"
#include "allocator.h"
+/** Expands a UCX string as printf arguments. */
+#define CX_SFMT(s) (int) (s).length, (s).ptr
+
+/** Format specifier for a UCX string */
+#define CX_PRIstr ".*s"
+
/**
* The maximum length of the "needle" in cx_strstr() that can use SBO.
*/
@@ -151,7 +157,7 @@ extern "C" {
*
* @param literal the string literal
*/
-#define CX_STR(literal) (cxstring){literal, sizeof(literal) - 1}
+#define CX_STR(literal) ((cxstring){literal, sizeof(literal) - 1})
#endif
@@ -257,6 +263,10 @@ cx_attr_nodiscard
static inline cxstring cx_strcast(cxstring str) {
return str;
}
+cx_attr_nodiscard
+static inline cxstring cx_strcast(const char *str) {
+ return cx_str(str);
+}
extern "C" {
#else
/**
@@ -280,6 +290,17 @@ static inline cxstring cx_strcast_c(cxstring str) {
return str;
}
+/**
+ * Internal function, do not use.
+ * @param str
+ * @return
+ * @see cx_strcast()
+ */
+cx_attr_nodiscard
+static inline cxstring cx_strcast_z(const char *str) {
+ return cx_str(str);
+}
+
/**
* Casts a mutable string to an immutable string.
*
@@ -294,12 +315,13 @@ static inline cxstring cx_strcast_c(cxstring str) {
*/
#define cx_strcast(str) _Generic((str), \
cxmutstr: cx_strcast_m, \
- cxstring: cx_strcast_c) \
- (str)
+ cxstring: cx_strcast_c, \
+ const char*: cx_strcast_z, \
+ char *: cx_strcast_z) (str)
#endif
/**
- * Passes the pointer in this string to @c free().
+ * Passes the pointer in this string to the cxDefaultAllocator's @c free() function.
*
* The pointer in the struct is set to @c NULL and the length is set to zero
* which means that this function protects you against double-free.
@@ -333,6 +355,46 @@ void cx_strfree_a(
cxmutstr *str
);
+/**
+ * Copies a string.
+ *
+ * The memory in the @p dest structure is either allocated or re-allocated to fit the entire
+ * source string, including a zero-terminator.
+ *
+ * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is.
+ *
+ * @param alloc the allocator
+ * @param dest a pointer to the structure where to copy the contents to
+ * @param src the source string
+ *
+ * @retval zero success
+ * @retval non-zero if re-allocation failed
+ */
+cx_attr_nonnull_arg(1)
+cx_attr_export
+int cx_strcpy_a(
+ const CxAllocator *alloc,
+ cxmutstr *dest,
+ cxstring src
+);
+
+
+/**
+ * Copies a string.
+ *
+ * The memory in the @p dest structure is either allocated or re-allocated to fit the entire
+ * source string, including a zero-terminator.
+ *
+ * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is.
+ *
+ * @param dest (@c cxmutstr*) a pointer to the structure where to copy the contents to
+ * @param src (@c cxstring) the source string
+ *
+ * @retval zero success
+ * @retval non-zero if re-allocation failed
+ */
+#define cx_strcpy(dest, src) cx_strcpy_a(cxDefaultAllocator, dest, src)
+
/**
* Returns the accumulated length of all specified strings.
*
@@ -408,7 +470,7 @@ cx_strcat_ma(alloc, cx_mutstrn(NULL, 0), count, __VA_ARGS__)
/**
* Concatenates strings and returns a new string.
*
- * The resulting string will be allocated by standard @c malloc().
+ * The resulting string will be allocated by the cxDefaultAllocator.
* So developers @em must pass the return value to cx_strfree() eventually.
*
* If memory allocation fails, the pointer in the returned string will
@@ -428,7 +490,7 @@ cx_strcat_ma(cxDefaultAllocator, cx_mutstrn(NULL, 0), count, __VA_ARGS__)
/**
* Concatenates strings.
*
- * The resulting string will be allocated by standard @c malloc().
+ * The resulting string will be allocated by the cxDefaultAllocator.
* So developers @em must pass the return value to cx_strfree() eventually.
*
* If @p str already contains a string, the memory will be reallocated and
@@ -879,13 +941,13 @@ cxmutstr cx_strdup_a_(
* @see cx_strfree_a()
*/
#define cx_strdup_a(allocator, string) \
- cx_strdup_a_((allocator), cx_strcast((string)))
+ cx_strdup_a_((allocator), cx_strcast(string))
/**
* Creates a duplicate of the specified string.
*
- * The new string will contain a copy allocated by standard
- * @c malloc(). So developers @em must pass the return value to cx_strfree().
+ * The new string will contain a copy allocated by the cxDefaultAllocator.
+ * So developers @em must pass the return value to cx_strfree().
*
* @note The returned string is guaranteed to be zero-terminated.
*
@@ -894,7 +956,7 @@ cxmutstr cx_strdup_a_(
* @see cx_strdup_a()
* @see cx_strfree()
*/
-#define cx_strdup(string) cx_strdup_a_(cxDefaultAllocator, string)
+#define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string)
/**
* Omits leading and trailing spaces.
@@ -1016,7 +1078,7 @@ cxmutstr cx_strreplacen_a(
*
* Replaces at most @p replmax occurrences.
*
- * The returned string will be allocated by @c malloc() and is guaranteed
+ * The returned string will be allocated by the cxDefaultAllocator and is guaranteed
* to be zero-terminated.
*
* If allocation fails, or the input string is empty,
@@ -1052,7 +1114,7 @@ cx_strreplacen_a(allocator, str, search, replacement, SIZE_MAX)
/**
* Replaces a string with another string.
*
- * The returned string will be allocated by @c malloc() and is guaranteed
+ * The returned string will be allocated by the cxDefaultAllocator and is guaranteed
* to be zero-terminated.
*
* If allocation fails, or the input string is empty,
@@ -1091,7 +1153,7 @@ CxStrtokCtx cx_strtok_(
* @return (@c CxStrtokCtx) a new string tokenization context
*/
#define cx_strtok(str, delim, limit) \
- cx_strtok_(cx_strcast((str)), cx_strcast((delim)), (limit))
+ cx_strtok_(cx_strcast(str), cx_strcast(delim), (limit))
/**
* Returns the next token.
diff --git a/ucx/cx/tree.h b/ucx/cx/tree.h
index b7f49b5..14832db 100644
--- a/ucx/cx/tree.h
+++ b/ucx/cx/tree.h
@@ -120,6 +120,7 @@ typedef struct cx_tree_iterator_s {
size_t stack_size;
/**
* The current depth in the tree.
+ * The node with which the iteration starts has depth 1.
*/
size_t depth;
};
@@ -135,6 +136,7 @@ struct cx_tree_visitor_queue_s {
void *node;
/**
* The depth of the node.
+ * The first visited node has depth 1.
*/
size_t depth;
/**
@@ -211,7 +213,7 @@ typedef struct cx_tree_visitor_s {
*/
cx_attr_nonnull
static inline void cxTreeIteratorDispose(CxTreeIterator *iter) {
- free(iter->stack);
+ cxFreeDefault(iter->stack);
iter->stack = NULL;
}
@@ -224,7 +226,7 @@ static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
struct cx_tree_visitor_queue_s *q = visitor->queue_next;
while (q != NULL) {
struct cx_tree_visitor_queue_s *next = q->next;
- free(q);
+ cxFreeDefault(q);
q = next;
}
}
@@ -441,7 +443,7 @@ int cx_tree_search(
* Creates a depth-first iterator for a tree with the specified root node.
*
* @note A tree iterator needs to maintain a stack of visited nodes, which is
- * allocated using stdlib malloc().
+ * allocated using the cxDefaultAllocator.
* When the iterator becomes invalid, this memory is automatically released.
* However, if you wish to cancel the iteration before the iterator becomes
* invalid by itself, you MUST call cxTreeIteratorDispose() manually to release
@@ -469,8 +471,8 @@ CxTreeIterator cx_tree_iterator(
/**
* Creates a breadth-first iterator for a tree with the specified root node.
*
- * @note A tree visitor needs to maintain a queue of to be visited nodes, which
- * is allocated using stdlib malloc().
+ * @note A tree visitor needs to maintain a queue of to-be visited nodes, which
+ * is allocated using the cxDefaultAllocator.
* When the visitor becomes invalid, this memory is automatically released.
* However, if you wish to cancel the iteration before the visitor becomes
* invalid by itself, you MUST call cxTreeVisitorDispose() manually to release
@@ -956,7 +958,7 @@ void cxTreeFree(CxTree *tree);
* will free the nodes with the allocator's free() method.
*
* @param allocator the allocator that shall be used
- * (if @c NULL, a default stdlib allocator will be used)
+ * (if @c NULL, the cxDefaultAllocator will be used)
* @param create_func a function that creates new nodes
* @param search_func a function that compares two nodes
* @param search_data_func a function that compares a node with data
@@ -1020,7 +1022,7 @@ cx_tree_node_base_layout)
* tree, you need to specify those functions afterwards.
*
* @param allocator the allocator that was used for nodes of the wrapped tree
- * (if @c NULL, a default stdlib allocator is assumed)
+ * (if @c NULL, the cxDefaultAllocator is assumed)
* @param root the root node of the tree that shall be wrapped
* @param loc_parent offset in the node struct for the parent pointer
* @param loc_children offset in the node struct for the children linked list
@@ -1187,6 +1189,18 @@ cx_attr_nodiscard
cx_attr_export
size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root);
+/**
+ * Determines the size of the entire tree.
+ *
+ * @param tree the tree
+ * @return the tree size, counting the root as one
+ */
+cx_attr_nonnull
+cx_attr_nodiscard
+static inline size_t cxTreeSize(CxTree *tree) {
+ return tree->size;
+}
+
/**
* Determines the depth of the entire tree.
*
diff --git a/ucx/json.c b/ucx/json.c
index 4993d97..484c7d3 100644
--- a/ucx/json.c
+++ b/ucx/json.c
@@ -500,7 +500,7 @@ static cxmutstr escape_string(cxmutstr str, bool escape_slash) {
if (all_printable && escape) {
size_t capa = str.length + 32;
- char *space = malloc(capa);
+ char *space = cxMallocDefault(capa);
if (space == NULL) return cx_mutstrn(NULL, 0);
cxBufferInit(&buf, space, capa, NULL, CX_BUFFER_AUTO_EXTEND);
cxBufferWrite(str.ptr, 1, i, &buf);
@@ -631,10 +631,10 @@ void cxJsonInit(CxJson *json, const CxAllocator *allocator) {
void cxJsonDestroy(CxJson *json) {
cxBufferDestroy(&json->buffer);
if (json->states != json->states_internal) {
- free(json->states);
+ cxFreeDefault(json->states);
}
if (json->vbuf != json->vbuf_internal) {
- free(json->vbuf);
+ cxFreeDefault(json->vbuf);
}
cxJsonValueFree(json->parsed);
json->parsed = NULL;
@@ -984,67 +984,67 @@ static void json_arr_free_temp(CxJsonValue** values, size_t count) {
if (values[i] == NULL) break;
cxJsonValueFree(values[i]);
}
- free(values);
+ cxFreeDefault(values);
}
// LCOV_EXCL_STOP
int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) {
- CxJsonValue** values = calloc(count, sizeof(CxJsonValue*));
+ CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*));
if (values == NULL) return -1;
for (size_t i = 0; i < count; i++) {
values[i] = cxJsonCreateNumber(arr->allocator, num[i]);
if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; }
}
int ret = cxJsonArrAddValues(arr, values, count);
- free(values);
+ cxFreeDefault(values);
return ret;
}
int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) {
- CxJsonValue** values = calloc(count, sizeof(CxJsonValue*));
+ CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*));
if (values == NULL) return -1;
for (size_t i = 0; i < count; i++) {
values[i] = cxJsonCreateInteger(arr->allocator, num[i]);
if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; }
}
int ret = cxJsonArrAddValues(arr, values, count);
- free(values);
+ cxFreeDefault(values);
return ret;
}
int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) {
- CxJsonValue** values = calloc(count, sizeof(CxJsonValue*));
+ CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*));
if (values == NULL) return -1;
for (size_t i = 0; i < count; i++) {
values[i] = cxJsonCreateString(arr->allocator, str[i]);
if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; }
}
int ret = cxJsonArrAddValues(arr, values, count);
- free(values);
+ cxFreeDefault(values);
return ret;
}
int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) {
- CxJsonValue** values = calloc(count, sizeof(CxJsonValue*));
+ CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*));
if (values == NULL) return -1;
for (size_t i = 0; i < count; i++) {
values[i] = cxJsonCreateCxString(arr->allocator, str[i]);
if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; }
}
int ret = cxJsonArrAddValues(arr, values, count);
- free(values);
+ cxFreeDefault(values);
return ret;
}
int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) {
- CxJsonValue** values = calloc(count, sizeof(CxJsonValue*));
+ CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*));
if (values == NULL) return -1;
for (size_t i = 0; i < count; i++) {
values[i] = cxJsonCreateLiteral(arr->allocator, lit[i]);
if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; }
}
int ret = cxJsonArrAddValues(arr, values, count);
- free(values);
+ cxFreeDefault(values);
return ret;
}
diff --git a/ucx/linked_list.c b/ucx/linked_list.c
index 3833d44..7cd2ff2 100644
--- a/ucx/linked_list.c
+++ b/ucx/linked_list.c
@@ -401,7 +401,7 @@ static void cx_linked_list_sort_merge(
) {
void *sbo[CX_LINKED_LIST_SORT_SBO_SIZE];
void **sorted = length >= CX_LINKED_LIST_SORT_SBO_SIZE ?
- malloc(sizeof(void *) * length) : sbo;
+ cxMallocDefault(sizeof(void *) * length) : sbo;
if (sorted == NULL) abort();
void *rc, *lc;
@@ -439,7 +439,7 @@ static void cx_linked_list_sort_merge(
*begin = sorted[0];
*end = sorted[length - 1];
if (sorted != sbo) {
- free(sorted);
+ cxFreeDefault(sorted);
}
}
@@ -613,7 +613,9 @@ static int cx_ll_insert_at(
// initialize new new_node
new_node->prev = new_node->next = NULL;
- memcpy(new_node->payload, elem, list->collection.elem_size);
+ if (elem != NULL) {
+ memcpy(new_node->payload, elem, list->collection.elem_size);
+ }
// insert
cx_linked_list *ll = (cx_linked_list *) list;
@@ -659,12 +661,26 @@ static size_t cx_ll_insert_array(
return n;
}
-static int cx_ll_insert_element(
+static void *cx_ll_insert_element(
struct cx_list_s *list,
size_t index,
const void *element
) {
- return 1 != cx_ll_insert_array(list, index, element, 1);
+ // out-of-bounds check
+ if (index > list->collection.size) return NULL;
+
+ // find position efficiently
+ cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1);
+
+ // perform first insert
+ if (cx_ll_insert_at(list, node, element)) return NULL;
+
+ // return a pointer to the data of the inserted node
+ if (node == NULL) {
+ return ((cx_linked_list *) list)->begin->payload;
+ } else {
+ return node->next->payload;
+ }
}
static _Thread_local cx_compare_func cx_ll_insert_sorted_cmp_func;
@@ -920,6 +936,8 @@ static size_t cx_ll_find_remove(
const void *elem,
bool remove
) {
+ if (list->collection.size == 0) return 0;
+
size_t index;
cx_linked_list *ll = ((cx_linked_list *) list);
cx_linked_list_node *node = cx_linked_list_find(
@@ -1054,12 +1072,12 @@ static int cx_ll_insert_iter(
}
return result;
} else {
- int result = cx_ll_insert_element(list, list->collection.size, elem);
- if (result == 0) {
- iter->elem_count++;
- iter->index = list->collection.size;
+ if (cx_ll_insert_element(list, list->collection.size, elem) == NULL) {
+ return 1;
}
- return result;
+ iter->elem_count++;
+ iter->index = list->collection.size;
+ return 0;
}
}
diff --git a/ucx/list.c b/ucx/list.c
index daf6b9e..7fbbb8b 100644
--- a/ucx/list.c
+++ b/ucx/list.c
@@ -62,7 +62,7 @@ static void cx_pl_destructor(struct cx_list_s *list) {
list->climpl->deallocate(list);
}
-static int cx_pl_insert_element(
+static void *cx_pl_insert_element(
struct cx_list_s *list,
size_t index,
const void *element
@@ -282,7 +282,7 @@ size_t cx_list_default_insert_array(
const char *src = data;
size_t i = 0;
for (; i < n; i++) {
- if (0 != invoke_list_func(
+ if (NULL == invoke_list_func(
insert_element, list, index + i,
src + (i * elem_size))) return i;
}
@@ -329,7 +329,7 @@ size_t cx_list_default_insert_sorted(
// insert the elements at location si
if (ins == 1) {
- if (0 != invoke_list_func(
+ if (NULL == invoke_list_func(
insert_element, list, di, src)) return inserted;
} else {
size_t r = invoke_list_func(insert_array, list, di, src, ins);
@@ -354,7 +354,7 @@ size_t cx_list_default_insert_sorted(
void cx_list_default_sort(struct cx_list_s *list) {
size_t elem_size = list->collection.elem_size;
size_t list_size = list->collection.size;
- void *tmp = malloc(elem_size * list_size);
+ void *tmp = cxMallocDefault(elem_size * list_size);
if (tmp == NULL) abort();
// copy elements from source array
@@ -377,7 +377,7 @@ void cx_list_default_sort(struct cx_list_s *list) {
loc += elem_size;
}
- free(tmp);
+ cxFreeDefault(tmp);
}
int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j) {
@@ -387,7 +387,7 @@ int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j) {
size_t elem_size = list->collection.elem_size;
- void *tmp = malloc(elem_size);
+ void *tmp = cxMallocDefault(elem_size);
if (tmp == NULL) return 1;
void *ip = invoke_list_func(at, list, i);
@@ -397,7 +397,7 @@ int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j) {
memcpy(ip, jp, elem_size);
memcpy(jp, tmp, elem_size);
- free(tmp);
+ cxFreeDefault(tmp);
return 0;
}
@@ -494,3 +494,24 @@ void cxListFree(CxList *list) {
if (list == NULL) return;
list->cl->deallocate(list);
}
+
+int cxListSet(
+ CxList *list,
+ size_t index,
+ const void *elem
+) {
+ if (index >= list->collection.size) {
+ return 1;
+ }
+
+ if (list->collection.store_pointer) {
+ // For pointer collections, always use climpl
+ void **target = list->climpl->at(list, index);
+ *target = (void *)elem;
+ } else {
+ void *target = list->cl->at(list, index);
+ memcpy(target, elem, list->collection.elem_size);
+ }
+
+ return 0;
+}
diff --git a/ucx/mempool.c b/ucx/mempool.c
index fea4d70..8711439 100644
--- a/ucx/mempool.c
+++ b/ucx/mempool.c
@@ -31,44 +31,69 @@
#include
#include
-struct cx_mempool_memory_s {
- /** The destructor. */
- cx_destructor_func destructor;
- /** The actual memory. */
- char c[];
-};
+static int cx_mempool_ensure_capacity(
+ struct cx_mempool_s *pool,
+ size_t needed_capacity
+) {
+ if (needed_capacity <= pool->capacity) return 0;
+ size_t newcap = pool->capacity >= 1000 ?
+ pool->capacity + 1000 : pool->capacity * 2;
+ size_t newmsize;
+ // LCOV_EXCL_START
+ if (pool->capacity > newcap
+ || cx_szmul(newcap, sizeof(void*), &newmsize)) {
+ errno = EOVERFLOW;
+ return 1;
+ } // LCOV_EXCL_STOP
+ void **newdata = cxRealloc(pool->base_allocator, pool->data, newmsize);
+ if (newdata == NULL) return 1;
+ pool->data = newdata;
+ pool->capacity = newcap;
+ return 0;
+}
-static void *cx_mempool_malloc(
+static int cx_mempool_ensure_registered_capacity(
+ struct cx_mempool_s *pool,
+ size_t needed_capacity
+) {
+ if (needed_capacity <= pool->registered_capacity) return 0;
+ // we do not expect so many registrations
+ size_t newcap = pool->registered_capacity + 8;
+ size_t newmsize;
+ // LCOV_EXCL_START
+ if (pool->registered_capacity > newcap || cx_szmul(newcap,
+ sizeof(struct cx_mempool_foreign_memory_s), &newmsize)) {
+ errno = EOVERFLOW;
+ return 1;
+ } // LCOV_EXCL_STOP
+ void *newdata = cxRealloc(pool->base_allocator, pool->registered, newmsize);
+ if (newdata == NULL) return 1;
+ pool->registered = newdata;
+ pool->registered_capacity = newcap;
+ return 0;
+}
+
+static void *cx_mempool_malloc_simple(
void *p,
size_t n
) {
struct cx_mempool_s *pool = p;
- if (pool->size >= pool->capacity) {
- size_t newcap = pool->capacity - (pool->capacity % 16) + 16;
- size_t newmsize;
- if (pool->capacity > newcap || cx_szmul(newcap,
- sizeof(struct cx_mempool_memory_s*), &newmsize)) {
- errno = EOVERFLOW;
- return NULL;
- }
- struct cx_mempool_memory_s **newdata = realloc(pool->data, newmsize);
- if (newdata == NULL) return NULL;
- pool->data = newdata;
- pool->capacity = newcap;
+ if (cx_mempool_ensure_capacity(pool, pool->size + 1)) {
+ return NULL; // LCOV_EXCL_LINE
}
- struct cx_mempool_memory_s *mem = malloc(sizeof(cx_destructor_func) + n);
+ struct cx_mempool_memory_s *mem =
+ cxMalloc(pool->base_allocator, sizeof(struct cx_mempool_memory_s) + n);
if (mem == NULL) return NULL;
-
- mem->destructor = pool->auto_destr;
+ mem->destructor = NULL;
pool->data[pool->size] = mem;
pool->size++;
return mem->c;
}
-static void *cx_mempool_calloc(
+static void *cx_mempool_calloc_simple(
void *p,
size_t nelem,
size_t elsize
@@ -78,53 +103,165 @@ static void *cx_mempool_calloc(
errno = EOVERFLOW;
return NULL;
}
- void *ptr = cx_mempool_malloc(p, msz);
+ void *ptr = cx_mempool_malloc_simple(p, msz);
if (ptr == NULL) return NULL;
memset(ptr, 0, nelem * elsize);
return ptr;
}
-static void *cx_mempool_realloc(
+static void cx_mempool_free_simple(
+ void *p,
+ void *ptr
+) {
+ if (!ptr) return;
+ struct cx_mempool_s *pool = p;
+
+ struct cx_mempool_memory_s *mem =
+ (void*) ((char *) ptr - sizeof(struct cx_mempool_memory_s));
+
+ for (size_t i = 0; i < pool->size; i++) {
+ if (mem == pool->data[i]) {
+ if (mem->destructor) {
+ mem->destructor(mem->c);
+ }
+ if (pool->destr) {
+ pool->destr(mem->c);
+ }
+ if (pool->destr2) {
+ pool->destr2(pool->destr2_data, mem->c);
+ }
+ cxFree(pool->base_allocator, mem);
+ size_t last_index = pool->size - 1;
+ if (i != last_index) {
+ pool->data[i] = pool->data[last_index];
+ pool->data[last_index] = NULL;
+ }
+ pool->size--;
+ return;
+ }
+ }
+ abort(); // LCOV_EXCL_LINE
+}
+
+static void *cx_mempool_realloc_simple(
void *p,
void *ptr,
size_t n
) {
+ if (ptr == NULL) {
+ return cx_mempool_malloc_simple(p, n);
+ }
+ if (n == 0) {
+ cx_mempool_free_simple(p, ptr);
+ return NULL;
+ }
struct cx_mempool_s *pool = p;
- struct cx_mempool_memory_s *mem, *newm;
- mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func));
- newm = realloc(mem, n + sizeof(cx_destructor_func));
+ const unsigned overhead = sizeof(struct cx_mempool_memory_s);
+ struct cx_mempool_memory_s *mem =
+ (void *) (((char *) ptr) - overhead);
+ struct cx_mempool_memory_s *newm =
+ cxRealloc(pool->base_allocator, mem, n + overhead);
if (newm == NULL) return NULL;
if (mem != newm) {
for (size_t i = 0; i < pool->size; i++) {
if (pool->data[i] == mem) {
pool->data[i] = newm;
- return ((char*)newm) + sizeof(cx_destructor_func);
+ return ((char*)newm) + overhead;
}
}
abort(); // LCOV_EXCL_LINE
} else {
- return ptr;
+ // unfortunately glibc() realloc seems to always move
+ return ptr; // LCOV_EXCL_LINE
+ }
+}
+
+static void cx_mempool_free_all_simple(const struct cx_mempool_s *pool) {
+ const bool has_destr = pool->destr;
+ const bool has_destr2 = pool->destr2;
+ for (size_t i = 0; i < pool->size; i++) {
+ struct cx_mempool_memory_s *mem = pool->data[i];
+ if (mem->destructor) {
+ mem->destructor(mem->c);
+ }
+ if (has_destr) {
+ pool->destr(mem->c);
+ }
+ if (has_destr2) {
+ pool->destr2(pool->destr2_data, mem->c);
+ }
+ cxFree(pool->base_allocator, mem);
+ }
+}
+
+static cx_allocator_class cx_mempool_simple_allocator_class = {
+ cx_mempool_malloc_simple,
+ cx_mempool_realloc_simple,
+ cx_mempool_calloc_simple,
+ cx_mempool_free_simple
+};
+
+static void *cx_mempool_malloc_advanced(
+ void *p,
+ size_t n
+) {
+ struct cx_mempool_s *pool = p;
+
+ if (cx_mempool_ensure_capacity(pool, pool->size + 1)) {
+ return NULL; // LCOV_EXCL_LINE
+ }
+
+ struct cx_mempool_memory2_s *mem =
+ cxMalloc(pool->base_allocator, sizeof(struct cx_mempool_memory2_s) + n);
+ if (mem == NULL) return NULL;
+ mem->destructor = NULL;
+ mem->data = NULL;
+ pool->data[pool->size] = mem;
+ pool->size++;
+
+ return mem->c;
+}
+
+static void *cx_mempool_calloc_advanced(
+ void *p,
+ size_t nelem,
+ size_t elsize
+) {
+ size_t msz;
+ if (cx_szmul(nelem, elsize, &msz)) {
+ errno = EOVERFLOW;
+ return NULL;
}
+ void *ptr = cx_mempool_malloc_advanced(p, msz);
+ if (ptr == NULL) return NULL;
+ memset(ptr, 0, nelem * elsize);
+ return ptr;
}
-static void cx_mempool_free(
+static void cx_mempool_free_advanced(
void *p,
void *ptr
) {
if (!ptr) return;
struct cx_mempool_s *pool = p;
- struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *)
- ((char *) ptr - sizeof(cx_destructor_func));
+ struct cx_mempool_memory2_s *mem =
+ (void*) ((char *) ptr - sizeof(struct cx_mempool_memory2_s));
for (size_t i = 0; i < pool->size; i++) {
if (mem == pool->data[i]) {
if (mem->destructor) {
- mem->destructor(mem->c);
+ mem->destructor(mem->data, mem->c);
+ }
+ if (pool->destr) {
+ pool->destr(mem->c);
}
- free(mem);
+ if (pool->destr2) {
+ pool->destr2(pool->destr2_data, mem->c);
+ }
+ cxFree(pool->base_allocator, mem);
size_t last_index = pool->size - 1;
if (i != last_index) {
pool->data[i] = pool->data[last_index];
@@ -137,19 +274,207 @@ static void cx_mempool_free(
abort(); // LCOV_EXCL_LINE
}
-void cxMempoolFree(CxMempool *pool) {
- if (pool == NULL) return;
- struct cx_mempool_memory_s *mem;
+static void *cx_mempool_realloc_advanced(
+ void *p,
+ void *ptr,
+ size_t n
+) {
+ if (ptr == NULL) {
+ return cx_mempool_malloc_advanced(p, n);
+ }
+ if (n == 0) {
+ cx_mempool_free_advanced(p, ptr);
+ return NULL;
+ }
+ struct cx_mempool_s *pool = p;
+
+ const unsigned overhead = sizeof(struct cx_mempool_memory2_s);
+ struct cx_mempool_memory2_s *mem =
+ (void *) (((char *) ptr) - overhead);
+ struct cx_mempool_memory2_s *newm =
+ cxRealloc(pool->base_allocator, mem, n + overhead);
+
+ if (newm == NULL) return NULL;
+ if (mem != newm) {
+ for (size_t i = 0; i < pool->size; i++) {
+ if (pool->data[i] == mem) {
+ pool->data[i] = newm;
+ return ((char*)newm) + overhead;
+ }
+ }
+ abort(); // LCOV_EXCL_LINE
+ } else {
+ // unfortunately glibc() realloc seems to always move
+ return ptr; // LCOV_EXCL_LINE
+ }
+}
+
+static void cx_mempool_free_all_advanced(const struct cx_mempool_s *pool) {
+ const bool has_destr = pool->destr;
+ const bool has_destr2 = pool->destr2;
for (size_t i = 0; i < pool->size; i++) {
- mem = pool->data[i];
+ struct cx_mempool_memory2_s *mem = pool->data[i];
if (mem->destructor) {
- mem->destructor(mem->c);
+ mem->destructor(mem->data, mem->c);
}
- free(mem);
+ if (has_destr) {
+ pool->destr(mem->c);
+ }
+ if (has_destr2) {
+ pool->destr2(pool->destr2_data, mem->c);
+ }
+ cxFree(pool->base_allocator, mem);
+ }
+}
+
+static cx_allocator_class cx_mempool_advanced_allocator_class = {
+ cx_mempool_malloc_advanced,
+ cx_mempool_realloc_advanced,
+ cx_mempool_calloc_advanced,
+ cx_mempool_free_advanced
+};
+
+
+static void *cx_mempool_malloc_pure(
+ void *p,
+ size_t n
+) {
+ struct cx_mempool_s *pool = p;
+
+ if (cx_mempool_ensure_capacity(pool, pool->size + 1)) {
+ return NULL; // LCOV_EXCL_LINE
}
- free(pool->data);
- free((void*) pool->allocator);
- free(pool);
+
+ void *mem = cxMalloc(pool->base_allocator, n);
+ if (mem == NULL) return NULL;
+ pool->data[pool->size] = mem;
+ pool->size++;
+
+ return mem;
+}
+
+static void *cx_mempool_calloc_pure(
+ void *p,
+ size_t nelem,
+ size_t elsize
+) {
+ size_t msz;
+ if (cx_szmul(nelem, elsize, &msz)) {
+ errno = EOVERFLOW;
+ return NULL;
+ }
+ void *ptr = cx_mempool_malloc_pure(p, msz);
+ if (ptr == NULL) return NULL;
+ memset(ptr, 0, nelem * elsize);
+ return ptr;
+}
+
+static void cx_mempool_free_pure(
+ void *p,
+ void *ptr
+) {
+ if (!ptr) return;
+ struct cx_mempool_s *pool = p;
+
+ for (size_t i = 0; i < pool->size; i++) {
+ if (ptr == pool->data[i]) {
+ if (pool->destr) {
+ pool->destr(ptr);
+ }
+ if (pool->destr2) {
+ pool->destr2(pool->destr2_data, ptr);
+ }
+ cxFree(pool->base_allocator, ptr);
+ size_t last_index = pool->size - 1;
+ if (i != last_index) {
+ pool->data[i] = pool->data[last_index];
+ pool->data[last_index] = NULL;
+ }
+ pool->size--;
+ return;
+ }
+ }
+ abort(); // LCOV_EXCL_LINE
+}
+
+static void *cx_mempool_realloc_pure(
+ void *p,
+ void *ptr,
+ size_t n
+) {
+ if (ptr == NULL) {
+ return cx_mempool_malloc_pure(p, n);
+ }
+ if (n == 0) {
+ cx_mempool_free_pure(p, ptr);
+ return NULL;
+ }
+ struct cx_mempool_s *pool = p;
+ void *newm = cxRealloc(pool->base_allocator, ptr, n);
+ if (newm == NULL) return NULL;
+ if (ptr != newm) {
+ for (size_t i = 0; i < pool->size; i++) {
+ if (pool->data[i] == ptr) {
+ pool->data[i] = newm;
+ return newm;
+ }
+ }
+ abort(); // LCOV_EXCL_LINE
+ } else {
+ // unfortunately glibc() realloc seems to always move
+ return ptr; // LCOV_EXCL_LINE
+ }
+}
+
+static void cx_mempool_free_all_pure(const struct cx_mempool_s *pool) {
+ const bool has_destr = pool->destr;
+ const bool has_destr2 = pool->destr2;
+ for (size_t i = 0; i < pool->size; i++) {
+ void *mem = pool->data[i];
+ if (has_destr) {
+ pool->destr(mem);
+ }
+ if (has_destr2) {
+ pool->destr2(pool->destr2_data, mem);
+ }
+ cxFree(pool->base_allocator, mem);
+ }
+}
+
+static cx_allocator_class cx_mempool_pure_allocator_class = {
+ cx_mempool_malloc_pure,
+ cx_mempool_realloc_pure,
+ cx_mempool_calloc_pure,
+ cx_mempool_free_pure
+};
+
+static void cx_mempool_free_foreign(const struct cx_mempool_s *pool) {
+ for (size_t i = 0; i < pool->registered_size; i++) {
+ struct cx_mempool_foreign_memory_s info = pool->registered[i];
+ if (info.destr2_data == NULL) {
+ if (info.destr) {
+ info.destr(info.mem);
+ }
+ } else {
+ info.destr2(info.destr2_data, info.mem);
+ }
+ }
+}
+
+void cxMempoolFree(CxMempool *pool) {
+ if (pool == NULL) return;
+ if (pool->allocator->cl == &cx_mempool_simple_allocator_class) {
+ cx_mempool_free_all_simple(pool);
+ } else if (pool->allocator->cl == &cx_mempool_advanced_allocator_class) {
+ cx_mempool_free_all_advanced(pool);
+ } else {
+ cx_mempool_free_all_pure(pool);
+ }
+ cx_mempool_free_foreign(pool);
+ cxFree(pool->base_allocator, pool->data);
+ cxFree(pool->base_allocator, pool->registered);
+ cxFree(pool->base_allocator, (void*) pool->allocator);
+ cxFree(pool->base_allocator, pool);
}
void cxMempoolSetDestructor(
@@ -159,18 +484,26 @@ void cxMempoolSetDestructor(
*(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func;
}
+void cxMempoolSetDestructor2(
+ void *ptr,
+ cx_destructor_func2 func,
+ void *data
+) {
+ struct cx_mempool_memory2_s *info =
+ (void*)((char *) ptr - sizeof(struct cx_mempool_memory2_s));
+ info->destructor = func;
+ info->data = data;
+}
+
void cxMempoolRemoveDestructor(void *ptr) {
*(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = NULL;
}
-struct cx_mempool_foreign_mem_s {
- cx_destructor_func destr;
- void* mem;
-};
-
-static void cx_mempool_destr_foreign_mem(void* ptr) {
- struct cx_mempool_foreign_mem_s *fm = ptr;
- fm->destr(fm->mem);
+void cxMempoolRemoveDestructor2(void *ptr) {
+ struct cx_mempool_memory2_s *info =
+ (void*)((char *) ptr - sizeof(struct cx_mempool_memory2_s));
+ info->destructor = NULL;
+ info->data = NULL;
}
int cxMempoolRegister(
@@ -178,60 +511,206 @@ int cxMempoolRegister(
void *memory,
cx_destructor_func destr
) {
- struct cx_mempool_foreign_mem_s *fm = cx_mempool_malloc(
- pool,
- sizeof(struct cx_mempool_foreign_mem_s)
- );
- if (fm == NULL) return 1;
+ if (cx_mempool_ensure_registered_capacity(pool, pool->registered_size + 1)) {
+ return 1; // LCOV_EXCL_LINE
+ }
- fm->mem = memory;
- fm->destr = destr;
- *(cx_destructor_func *) ((char *) fm - sizeof(cx_destructor_func)) = cx_mempool_destr_foreign_mem;
+ pool->registered[pool->registered_size++] =
+ (struct cx_mempool_foreign_memory_s) {
+ .mem = memory,
+ .destr = destr,
+ .destr2_data = NULL
+ };
return 0;
}
-static cx_allocator_class cx_mempool_allocator_class = {
- cx_mempool_malloc,
- cx_mempool_realloc,
- cx_mempool_calloc,
- cx_mempool_free
-};
+int cxMempoolRegister2(
+ CxMempool *pool,
+ void *memory,
+ cx_destructor_func2 destr,
+ void *data
+) {
+ if (cx_mempool_ensure_registered_capacity(pool, pool->registered_size + 1)) {
+ return 1; // LCOV_EXCL_LINE
+ }
+
+ pool->registered[pool->registered_size++] =
+ (struct cx_mempool_foreign_memory_s) {
+ .mem = memory,
+ .destr2 = destr,
+ .destr2_data = data
+ };
+
+ return 0;
+}
CxMempool *cxMempoolCreate(
size_t capacity,
- cx_destructor_func destr
+ enum cx_mempool_type type
) {
+ if (capacity == 0) capacity = 16;
size_t poolsize;
- if (cx_szmul(capacity, sizeof(struct cx_mempool_memory_s*), &poolsize)) {
+ if (cx_szmul(capacity, sizeof(void*), &poolsize)) {
+ // LCOV_EXCL_START
errno = EOVERFLOW;
return NULL;
- }
-
- struct cx_mempool_s *pool =
- malloc(sizeof(struct cx_mempool_s));
- if (pool == NULL) return NULL;
+ } // LCOV_EXCL_STOP
- CxAllocator *provided_allocator = malloc(sizeof(CxAllocator));
+ CxAllocator *provided_allocator = cxMallocDefault(sizeof(CxAllocator));
if (provided_allocator == NULL) { // LCOV_EXCL_START
- free(pool);
return NULL;
} // LCOV_EXCL_STOP
- provided_allocator->cl = &cx_mempool_allocator_class;
- provided_allocator->data = pool;
+ CxMempool *pool = cxCallocDefault(1, sizeof(CxMempool));
+ if (pool == NULL) { // LCOV_EXCL_START
+ cxFreeDefault(provided_allocator);
+ return NULL;
+ } // LCOV_EXCL_STOP
+
+ provided_allocator->data = pool;
+ *((const CxAllocator**)&pool->base_allocator) = cxDefaultAllocator;
pool->allocator = provided_allocator;
+ if (type == CX_MEMPOOL_TYPE_SIMPLE) {
+ provided_allocator->cl = &cx_mempool_simple_allocator_class;
+ } else if (type == CX_MEMPOOL_TYPE_ADVANCED) {
+ provided_allocator->cl = &cx_mempool_advanced_allocator_class;
+ } else {
+ provided_allocator->cl = &cx_mempool_pure_allocator_class;
+ }
- pool->data = malloc(poolsize);
+ pool->data = cxMallocDefault(poolsize);
if (pool->data == NULL) { // LCOV_EXCL_START
- free(provided_allocator);
- free(pool);
+ cxFreeDefault(provided_allocator);
+ cxFreeDefault(pool);
return NULL;
} // LCOV_EXCL_STOP
pool->size = 0;
pool->capacity = capacity;
- pool->auto_destr = destr;
return pool;
}
+
+void cxMempoolGlobalDestructor(CxMempool *pool, cx_destructor_func fnc) {
+ pool->destr = fnc;
+}
+
+void cxMempoolGlobalDestructor2(CxMempool *pool, cx_destructor_func2 fnc, void *data) {
+ pool->destr2 = fnc;
+ pool->destr2_data = data;
+}
+
+static void cx_mempool_free_transferred_allocator(void *base_al, void *al) {
+ cxFree(base_al, al);
+}
+
+int cxMempoolTransfer(
+ CxMempool *source,
+ CxMempool *dest
+) {
+ // safety checks
+ if (source == dest) return 1;
+ if (source->allocator->cl != dest->allocator->cl) return 1;
+ if (source->base_allocator->cl != dest->base_allocator->cl) return 1;
+
+ // ensure enough capacity in the destination pool
+ if (cx_mempool_ensure_capacity(dest, dest->size + source->size)) {
+ return 1; // LCOV_EXCL_LINE
+ }
+ if (cx_mempool_ensure_registered_capacity(dest,
+ dest->registered_size + source->registered_size)) {
+ return 1; // LCOV_EXCL_LINE
+ }
+
+ // allocate a replacement allocator for the source pool
+ CxAllocator *new_source_allocator =
+ cxMalloc(source->base_allocator, sizeof(CxAllocator));
+ if (new_source_allocator == NULL) { // LCOV_EXCL_START
+ return 1;
+ } // LCOV_EXCL_STOP
+ new_source_allocator->cl = source->allocator->cl;
+ new_source_allocator->data = source;
+
+ // transfer all the data
+ memcpy(&dest->data[dest->size], source->data, sizeof(void*)*source->size);
+ dest->size += source->size;
+
+ // transfer all registered memory
+ memcpy(&dest->registered[dest->registered_size], source->registered,
+ sizeof(struct cx_mempool_foreign_memory_s) * source->size);
+ dest->registered_size += source->registered_size;
+
+ // register the old allocator with the new pool
+ // we have to remove const-ness for this, but that's okay here
+ // also register the base allocator, s.t. the pool knows how to free it
+ CxAllocator *transferred_allocator = (CxAllocator*) source->allocator;
+ transferred_allocator->data = dest;
+ cxMempoolRegister2(dest, transferred_allocator,
+ cx_mempool_free_transferred_allocator, (void*)source->base_allocator);
+
+ // prepare the source pool for re-use
+ source->allocator = new_source_allocator;
+ memset(source->data, 0, source->size * sizeof(void*));
+ memset(source->registered, 0,
+ source->registered_size * sizeof(struct cx_mempool_foreign_memory_s));
+ source->size = 0;
+ source->registered_size = 0;
+
+ return 0;
+}
+
+int cxMempoolTransferObject(
+ CxMempool *source,
+ CxMempool *dest,
+ const void *obj
+) {
+ // safety checks
+ if (source == dest) return 1;
+ if (source->allocator->cl != dest->allocator->cl) return 1;
+ if (source->base_allocator->cl != dest->base_allocator->cl) return 1;
+
+ // search for the object
+ for (size_t i = 0; i < source->size; i++) {
+ struct cx_mempool_memory_s *mem = source->data[i];
+ if (mem->c == obj) {
+ // first, make sure that the dest pool can take the object
+ if (cx_mempool_ensure_capacity(dest, dest->size + 1)) {
+ return 1; // LCOV_EXCL_LINE
+ }
+ // remove from the source pool
+ size_t last_index = source->size - 1;
+ if (i != last_index) {
+ source->data[i] = source->data[last_index];
+ source->data[last_index] = NULL;
+ }
+ source->size--;
+ // add to the target pool
+ dest->data[dest->size++] = mem;
+ return 0;
+ }
+ }
+ // search in the registered objects
+ for (size_t i = 0; i < source->registered_size; i++) {
+ struct cx_mempool_foreign_memory_s *mem = &source->registered[i];
+ if (mem->mem == obj) {
+ // first, make sure that the dest pool can take the object
+ if (cx_mempool_ensure_registered_capacity(dest,
+ dest->registered_size + 1)) {
+ return 1; // LCOV_EXCL_LINE
+ }
+ dest->registered[dest->registered_size++] = *mem;
+ // remove from the source pool
+ size_t last_index = source->registered_size - 1;
+ if (i != last_index) {
+ source->registered[i] = source->registered[last_index];
+ memset(&source->registered[last_index], 0,
+ sizeof(struct cx_mempool_foreign_memory_s));
+ }
+ source->registered_size--;
+ return 0;
+ }
+ }
+ // not found
+ return 1;
+}
diff --git a/ucx/printf.c b/ucx/printf.c
index bf691cf..9d18673 100644
--- a/ucx/printf.c
+++ b/ucx/printf.c
@@ -68,7 +68,7 @@ int cx_vfprintf(
return (int) wfc(buf, 1, ret, stream);
} else {
int len = ret + 1;
- char *newbuf = malloc(len);
+ char *newbuf = cxMallocDefault(len);
if (!newbuf) { // LCOV_EXCL_START
va_end(ap2);
return -1;
@@ -79,7 +79,7 @@ int cx_vfprintf(
if (ret > 0) {
ret = (int) wfc(newbuf, 1, ret, stream);
}
- free(newbuf);
+ cxFreeDefault(newbuf);
}
return ret;
}
@@ -121,7 +121,7 @@ cxmutstr cx_vasprintf_a(
if (s.ptr) {
ret = vsnprintf(s.ptr, len, fmt, ap2);
if (ret < 0) {
- free(s.ptr);
+ cxFree(a, s.ptr);
s.ptr = NULL;
} else {
s.length = (size_t) ret;
@@ -132,7 +132,13 @@ cxmutstr cx_vasprintf_a(
return s;
}
-int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ) {
+int cx_sprintf_a(
+ const CxAllocator *alloc,
+ char **str,
+ size_t *len,
+ const char *fmt,
+ ...
+) {
va_list ap;
va_start(ap, fmt);
int ret = cx_vsprintf_a(alloc, str, len, fmt, ap);
@@ -140,7 +146,13 @@ int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, .
return ret;
}
-int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap) {
+int cx_vsprintf_a(
+ const CxAllocator *alloc,
+ char **str,
+ size_t *len,
+ const char *fmt,
+ va_list ap
+) {
va_list ap2;
va_copy(ap2, ap);
int ret = vsnprintf(*str, *len, fmt, ap);
@@ -162,7 +174,14 @@ int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt,
return ret;
}
-int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ) {
+int cx_sprintf_sa(
+ const CxAllocator *alloc,
+ char *buf,
+ size_t *len,
+ char **str,
+ const char *fmt,
+ ...
+) {
va_list ap;
va_start(ap, fmt);
int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap);
@@ -170,7 +189,14 @@ int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const
return ret;
}
-int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap) {
+int cx_vsprintf_sa(
+ const CxAllocator *alloc,
+ char *buf,
+ size_t *len,
+ char **str,
+ const char *fmt,
+ va_list ap
+) {
va_list ap2;
va_copy(ap2, ap);
int ret = vsnprintf(buf, *len, fmt, ap);
diff --git a/ucx/properties.c b/ucx/properties.c
index 23f79b3..4593602 100644
--- a/ucx/properties.c
+++ b/ucx/properties.c
@@ -287,7 +287,7 @@ static int cx_properties_read_init_file(
cx_attr_unused CxProperties *prop,
CxPropertiesSource *src
) {
- src->data_ptr = malloc(src->data_size);
+ src->data_ptr = cxMallocDefault(src->data_size);
if (src->data_ptr == NULL) return 1;
return 0;
}
@@ -296,7 +296,7 @@ static void cx_properties_read_clean_file(
cx_attr_unused CxProperties *prop,
CxPropertiesSource *src
) {
- free(src->data_ptr);
+ cxFreeDefault(src->data_ptr);
}
CxPropertiesSource cxPropertiesStringSource(cxstring str) {
diff --git a/ucx/streams.c b/ucx/streams.c
index 2efc035..bee37da 100644
--- a/ucx/streams.c
+++ b/ucx/streams.c
@@ -27,6 +27,7 @@
*/
#include "cx/streams.h"
+#include "cx/allocator.h"
#ifndef CX_STREAM_BCOPY_BUF_SIZE
#define CX_STREAM_BCOPY_BUF_SIZE 8192
@@ -57,7 +58,7 @@ size_t cx_stream_bncopy(
lbuf = buf;
} else {
if (bufsize == 0) bufsize = CX_STREAM_BCOPY_BUF_SIZE;
- lbuf = malloc(bufsize);
+ lbuf = cxMallocDefault(bufsize);
if (lbuf == NULL) return 0;
}
@@ -74,7 +75,7 @@ size_t cx_stream_bncopy(
}
if (lbuf != buf) {
- free(lbuf);
+ cxFreeDefault(lbuf);
}
return ncp;
diff --git a/ucx/string.c b/ucx/string.c
index 14b732e..61d88f3 100644
--- a/ucx/string.c
+++ b/ucx/string.c
@@ -65,7 +65,7 @@ cxstring cx_strn(
void cx_strfree(cxmutstr *str) {
if (str == NULL) return;
- free(str->ptr);
+ cxFreeDefault(str->ptr);
str->ptr = NULL;
str->length = 0;
}
@@ -80,6 +80,22 @@ void cx_strfree_a(
str->length = 0;
}
+int cx_strcpy_a(
+ const CxAllocator *alloc,
+ cxmutstr *dest,
+ cxstring src
+) {
+ if (cxReallocate(alloc, &dest->ptr, src.length + 1)) {
+ return 1;
+ }
+
+ memcpy(dest->ptr, src.ptr, src.length);
+ dest->length = src.length;
+ dest->ptr[dest->length] = '\0';
+
+ return 0;
+}
+
size_t cx_strlen(
size_t count,
...
@@ -106,27 +122,16 @@ cxmutstr cx_strcat_ma(
...
) {
if (count == 0) return str;
-
- cxstring strings_stack[8];
- cxstring *strings;
- if (count > 8) {
- strings = calloc(count, sizeof(cxstring));
- if (strings == NULL) {
- return (cxmutstr) {NULL, 0};
- }
- } else {
- strings = strings_stack;
- }
-
va_list ap;
va_start(ap, count);
+ va_list ap2;
+ va_copy(ap2, ap);
- // get all args and overall length
+ // compute overall length
bool overflow = false;
size_t slen = str.length;
for (size_t i = 0; i < count; i++) {
- cxstring s = va_arg (ap, cxstring);
- strings[i] = s;
+ cxstring s = va_arg(ap, cxstring);
if (slen > SIZE_MAX - str.length) overflow = true;
slen += s.length;
}
@@ -134,10 +139,8 @@ cxmutstr cx_strcat_ma(
// abort in case of overflow
if (overflow) {
+ va_end(ap2);
errno = EOVERFLOW;
- if (strings != strings_stack) {
- free(strings);
- }
return (cxmutstr) { NULL, 0 };
}
@@ -149,9 +152,7 @@ cxmutstr cx_strcat_ma(
newstr = cxRealloc(alloc, str.ptr, slen + 1);
}
if (newstr == NULL) {
- if (strings != strings_stack) {
- free(strings);
- }
+ va_end(ap2);
return (cxmutstr) {NULL, 0};
}
str.ptr = newstr;
@@ -160,19 +161,15 @@ cxmutstr cx_strcat_ma(
size_t pos = str.length;
str.length = slen;
for (size_t i = 0; i < count; i++) {
- cxstring s = strings[i];
+ cxstring s = va_arg(ap2, cxstring);
memcpy(str.ptr + pos, s.ptr, s.length);
pos += s.length;
}
+ va_end(ap2);
// terminate string
str.ptr[str.length] = '\0';
- // free temporary array
- if (strings != strings_stack) {
- free(strings);
- }
-
return str;
}
@@ -289,8 +286,9 @@ cxstring cx_strstr(
// check needle length and use appropriate prefix table
// if the pattern exceeds static prefix table, allocate on the heap
const bool useheap = needle.length >= CX_STRSTR_SBO_SIZE;
- register size_t *ptable = useheap ? calloc(needle.length + 1,
- sizeof(size_t)) : s_prefix_table;
+ register size_t *ptable = useheap
+ ? cxCallocDefault(needle.length + 1, sizeof(size_t))
+ : s_prefix_table;
// keep counter in registers
register size_t i, j;
@@ -328,7 +326,7 @@ cxstring cx_strstr(
// if prefix table was allocated on the heap, free it
if (useheap) {
- free(ptable);
+ cxFreeDefault(ptable);
}
return result;
@@ -588,27 +586,6 @@ bool cx_strcasesuffix(
#endif
}
-#ifndef CX_STRREPLACE_INDEX_BUFFER_SIZE
-#define CX_STRREPLACE_INDEX_BUFFER_SIZE 64
-#endif
-
-struct cx_strreplace_ibuf {
- size_t *buf;
- struct cx_strreplace_ibuf *next;
- unsigned int len;
-};
-
-static void cx_strrepl_free_ibuf(struct cx_strreplace_ibuf *buf) {
- // remember, the first data is on the stack!
- buf = buf->next;
- while (buf) {
- struct cx_strreplace_ibuf *next = buf->next;
- free(buf->buf);
- free(buf);
- buf = next;
- }
-}
-
cxmutstr cx_strreplacen_a(
const CxAllocator *allocator,
cxstring str,
@@ -616,108 +593,60 @@ cxmutstr cx_strreplacen_a(
cxstring replacement,
size_t replmax
) {
-
- if (search.length == 0 || search.length > str.length || replmax == 0)
+ // special cases
+ if (search.length == 0 || search.length > str.length || replmax == 0) {
return cx_strdup_a(allocator, str);
-
- // Compute expected buffer length
- size_t ibufmax = str.length / search.length;
- size_t ibuflen = replmax < ibufmax ? replmax : ibufmax;
- if (ibuflen > CX_STRREPLACE_INDEX_BUFFER_SIZE) {
- ibuflen = CX_STRREPLACE_INDEX_BUFFER_SIZE;
}
- // First index buffer can be on the stack
- struct cx_strreplace_ibuf ibuf, *curbuf = &ibuf;
- size_t ibuf_sbo[CX_STRREPLACE_INDEX_BUFFER_SIZE];
- ibuf.buf = ibuf_sbo;
- ibuf.next = NULL;
- ibuf.len = 0;
+ size_t in_len = str.length;
+ size_t search_len = search.length;
+ size_t repl_len = replacement.length;
- // Search occurrences
- cxstring searchstr = str;
- size_t found = 0;
- do {
- cxstring match = cx_strstr(searchstr, search);
- if (match.length > 0) {
- // Allocate next buffer in chain, if required
- if (curbuf->len == ibuflen) {
- struct cx_strreplace_ibuf *nextbuf =
- calloc(1, sizeof(struct cx_strreplace_ibuf));
- if (!nextbuf) {
- cx_strrepl_free_ibuf(&ibuf);
- return cx_mutstrn(NULL, 0);
- }
- nextbuf->buf = calloc(ibuflen, sizeof(size_t));
- if (!nextbuf->buf) {
- free(nextbuf);
- cx_strrepl_free_ibuf(&ibuf);
- return cx_mutstrn(NULL, 0);
- }
- curbuf->next = nextbuf;
- curbuf = nextbuf;
- }
-
- // Record match index
- found++;
- size_t idx = match.ptr - str.ptr;
- curbuf->buf[curbuf->len++] = idx;
- searchstr.ptr = match.ptr + search.length;
- searchstr.length = str.length - idx - search.length;
- } else {
- break;
- }
- } while (searchstr.length > 0 && found < replmax);
-
- // Allocate result string
- cxmutstr result;
- {
- long long adjlen = (long long) replacement.length - (long long) search.length;
- size_t rcount = 0;
- curbuf = &ibuf;
- do {
- rcount += curbuf->len;
- curbuf = curbuf->next;
- } while (curbuf);
- result.length = str.length + rcount * adjlen;
- result.ptr = cxMalloc(allocator, result.length + 1);
- if (!result.ptr) {
- cx_strrepl_free_ibuf(&ibuf);
- return cx_mutstrn(NULL, 0);
- }
+ // first run, count the occurrences
+ // and remember where the first is
+ size_t occurrences = 1;
+ cxstring first = cx_strstr(str, search);
+ if (first.length == 0) {
+ // special case, no replacements
+ return cx_strdup_a(allocator, str);
+ }
+ cxstring tmp = cx_strsubs(first, search_len);
+ while (occurrences < replmax &&
+ (tmp = cx_strstr(tmp, search)).length > 0) {
+ occurrences++;
+ tmp = cx_strsubs(tmp, search_len);
}
- // Build result string
- curbuf = &ibuf;
- size_t srcidx = 0;
- char *destptr = result.ptr;
- do {
- for (size_t i = 0; i < curbuf->len; i++) {
- // Copy source part up to next match
- size_t idx = curbuf->buf[i];
- size_t srclen = idx - srcidx;
- if (srclen > 0) {
- memcpy(destptr, str.ptr + srcidx, srclen);
- destptr += srclen;
- srcidx += srclen;
- }
-
- // Copy the replacement and skip the source pattern
- srcidx += search.length;
- memcpy(destptr, replacement.ptr, replacement.length);
- destptr += replacement.length;
- }
- curbuf = curbuf->next;
- } while (curbuf);
- memcpy(destptr, str.ptr + srcidx, str.length - srcidx);
-
- // Result is guaranteed to be zero-terminated
- result.ptr[result.length] = '\0';
+ // calculate necessary memory
+ signed long long diff_len = (signed long long) repl_len - search_len;
+ size_t out_len = in_len + diff_len * occurrences;
+ cxmutstr out = {
+ cxMalloc(allocator, out_len + 1),
+ out_len
+ };
+ if (out.ptr == NULL) return out;
+
+ // second run: perform the replacements
+ // but start where we found the first occurrence
+ const char *inp = str.ptr;
+ tmp = first;
+ char *outp = out.ptr;
+ while (occurrences-- > 0 && (tmp = cx_strstr(tmp, search)).length > 0) {
+ size_t copylen = tmp.ptr - inp;
+ memcpy(outp, inp, copylen);
+ outp += copylen;
+ memcpy(outp, replacement.ptr, repl_len);
+ outp += repl_len;
+ inp += copylen + search_len;
+ tmp = cx_strsubs(tmp, search_len);
+ }
- // Free index buffer
- cx_strrepl_free_ibuf(&ibuf);
+ // add the remaining string
+ size_t copylen = in_len - (inp - str.ptr);
+ memcpy(outp, inp, copylen);
+ out.ptr[out_len] = '\0';
- return result;
+ return out;
}
CxStrtokCtx cx_strtok_(
diff --git a/ucx/tree.c b/ucx/tree.c
index 397f908..1b2b38e 100644
--- a/ucx/tree.c
+++ b/ucx/tree.c
@@ -226,14 +226,14 @@ int cx_tree_search(
int ret_elem = sfunc(elem, node);
if (ret_elem == 0) {
// if found, exit the search
- *result = (void *) elem;
+ *result = elem;
ret = 0;
break;
} else if (ret_elem > 0 && ret_elem < ret) {
// new distance is better
*result = elem;
ret = ret_elem;
- } else {
+ } else if (ret_elem < 0 || ret_elem > ret) {
// not contained or distance is worse, skip entire subtree
cxTreeIteratorContinue(iter);
}
@@ -305,12 +305,12 @@ static void cx_tree_iter_next(void *it) {
if (children == NULL) {
// search for the next node
- void *next;
+ void *next = NULL;
cx_tree_iter_search_next:
- // check if there is a sibling
+ // check if there is a sibling, but only if we are not a (subtree-)root
if (iter->exiting) {
next = iter->node_next;
- } else {
+ } else if (iter->depth > 1) {
next = tree_next(iter->node);
iter->node_next = next;
}
@@ -326,7 +326,7 @@ static void cx_tree_iter_next(void *it) {
// invalidate the iterator and free the node stack
iter->node = iter->node_next = NULL;
iter->stack_capacity = iter->depth = 0;
- free(iter->stack);
+ cxFreeDefault(iter->stack);
iter->stack = NULL;
} else {
// the parent node can be obtained from the top of stack
@@ -386,7 +386,7 @@ CxTreeIterator cx_tree_iterator(
iter.node = root;
if (root != NULL) {
iter.stack_capacity = 16;
- iter.stack = malloc(sizeof(void *) * 16);
+ iter.stack = cxMallocDefault(sizeof(void *) * 16);
iter.stack[0] = root;
iter.counter = 1;
iter.depth = 1;
@@ -416,7 +416,7 @@ static void cx_tree_visitor_enqueue_siblings(
node = tree_next(node);
while (node != NULL) {
struct cx_tree_visitor_queue_s *q;
- q = malloc(sizeof(struct cx_tree_visitor_queue_s));
+ q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s));
q->depth = iter->queue_last->depth;
q->node = node;
iter->queue_last->next = q;
@@ -445,7 +445,7 @@ static void cx_tree_visitor_next(void *it) {
}
if (children != NULL) {
struct cx_tree_visitor_queue_s *q;
- q = malloc(sizeof(struct cx_tree_visitor_queue_s));
+ q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s));
q->depth = iter->depth + 1;
q->node = children;
if (iter->queue_last == NULL) {
@@ -474,7 +474,7 @@ static void cx_tree_visitor_next(void *it) {
assert(iter->queue_last == q);
iter->queue_last = NULL;
}
- free(q);
+ cxFreeDefault(q);
}
// increment the node counter
diff --git a/ui/Makefile b/ui/Makefile
index 6905986..ad5aad0 100644
--- a/ui/Makefile
+++ b/ui/Makefile
@@ -33,15 +33,16 @@ OBJ_DIR = ../build/
include common/objs.mk
-UI_LIB = ../build/lib/$(LIB_PREFIX)uitk$(LIB_EXT)
+UI_LIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT)
+UI_SHLIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(SHLIB_EXT)
include $(TOOLKIT)/objs.mk
OBJ = $(TOOLKITOBJS) $(COMMONOBJS)
-all: $(UI_LIB)
+all: $(UI_LIB) $(UI_SHLIB)
include $(TOOLKIT)/Makefile
$(COMMON_OBJPRE)uic_%$(OBJ_EXT): common/%.c
- $(CC) -o $@ -c -I../ucx/ $(CFLAGS) $(TK_CFLAGS) $<
+ $(CC) -o $@ -c -I../ucx/ $(CFLAGS) $(SHLIB_CFLAGS) $(TK_CFLAGS) $<
diff --git a/ui/common/args.c b/ui/common/args.c
new file mode 100644
index 0000000..e799889
--- /dev/null
+++ b/ui/common/args.c
@@ -0,0 +1,1586 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 "args.h"
+
+#include
+#include
+
+#include "../ui/container.h"
+
+/* ---------------------------- UiMenuItemArgs ---------------------------- */
+
+UiMenuItemArgs* ui_menuitem_args_new(void) {
+ UiMenuItemArgs *args = malloc(sizeof(UiMenuItemArgs));
+ memset(args, 0, sizeof(UiMenuItemArgs));
+ return args;
+}
+
+void ui_menuitem_args_set_label(UiMenuItemArgs *args, const char *label) {
+ args->label = strdup(label);
+}
+
+void ui_menuitem_args_set_stockid(UiMenuItemArgs *args, const char *stockid) {
+ args->stockid = strdup(stockid);
+}
+
+void ui_menuitem_args_set_icon(UiMenuItemArgs *args, const char *icon) {
+ args->icon = strdup(icon);
+}
+
+void ui_menuitem_args_set_onclick(UiMenuItemArgs *args, ui_callback callback) {
+ args->onclick = callback;
+}
+
+void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata) {
+ args->onclickdata = onclickdata;
+}
+
+void ui_menuitem_args_free(UiMenuItemArgs *args) {
+ free((void*)args->label);
+ free((void*)args->stockid);
+ free((void*)args->icon);
+ free(args);
+}
+
+
+/* ---------------------------- UiMenuToggleItemArgs ---------------------------- */
+
+UiMenuToggleItemArgs* ui_menutoggleitem_args_new(void) {
+ UiMenuToggleItemArgs *args = malloc(sizeof(UiMenuToggleItemArgs));
+ memset(args, 0, sizeof(UiMenuToggleItemArgs));
+ return args;
+}
+
+void ui_menutoggleitem_args_set_label(UiMenuToggleItemArgs *args, const char *label) {
+ args->label = strdup(label);
+}
+
+void ui_menutoggleitem_args_set_stockid(UiMenuToggleItemArgs *args, const char *stockid) {
+ args->stockid = strdup(stockid);
+}
+
+void ui_menutoggleitem_args_set_icon(UiMenuToggleItemArgs *args, const char *icon) {
+ args->icon = strdup(icon);
+}
+
+void ui_menutoggleitem_args_set_varname(UiMenuToggleItemArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_menutoggleitem_args_set_onchange(UiMenuToggleItemArgs *args, ui_callback callback) {
+ args->onchange = callback;
+}
+
+void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *onclickdata) {
+ args->onchangedata = onclickdata;
+}
+
+void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args) {
+ free((void*)args->label);
+ free((void*)args->stockid);
+ free((void*)args->icon);
+ free((void*)args->varname);
+ free(args);
+}
+
+/* --------------------------- UiMenuItemListArgs --------------------------- */
+
+UiMenuItemListArgs* ui_menuitemlist_args_new(void) {
+ UiMenuItemListArgs *args = malloc(sizeof(UiMenuItemListArgs));
+ memset(args, 0, sizeof(UiMenuItemListArgs));
+ return args;
+}
+
+void ui_menuitemlist_args_set_varname(UiMenuItemListArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc func) {
+ args->getvalue = func;
+}
+
+void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback) {
+ args->onselect = callback;
+}
+
+void ui_menuitemlist_args_set_onselectdata(UiMenuItemListArgs *args, void *data){
+ args->onselectdata = data;
+}
+
+void ui_menuitemlist_args_set_addseparator(UiMenuItemListArgs *args, UiBool value) {
+ args->addseparator = value;
+}
+
+void ui_menuitemlist_args_free(UiMenuItemListArgs *args){
+ free((void*)args->varname);
+ free(args);
+}
+
+/* --------------------------- UiToolbarItemArgs --------------------------- */
+
+UiToolbarItemArgs* ui_toolbar_item_args_new(void) {
+ UiToolbarItemArgs *args = malloc(sizeof(UiToolbarItemArgs));
+ memset(args, 0, sizeof(UiToolbarItemArgs));
+ return args;
+}
+
+void ui_toolbar_item_args_set_label(UiToolbarItemArgs *args, const char *label) {
+ args->label = strdup(label);
+}
+
+void ui_toolbar_item_args_set_stockid(UiToolbarItemArgs *args, const char *stockid) {
+ args->stockid = strdup(stockid);
+}
+
+void ui_toolbar_item_args_set_icon(UiToolbarItemArgs *args, const char *icon) {
+ args->icon = strdup(icon);
+}
+
+void ui_toolbar_item_args_set_onclick(UiToolbarItemArgs *args, ui_callback callback) {
+ args->onclick = callback;
+}
+
+void ui_toolbar_item_args_set_onclickdata(UiToolbarItemArgs *args, void *onclickdata) {
+ args->onclickdata = onclickdata;
+}
+
+void ui_toolbar_item_args_set_groups(UiToolbarItemArgs *args, int *groups) {
+ // TODO
+}
+void ui_toolbar_item_args_free(UiToolbarItemArgs *args) {
+ free((void*)args->label);
+ free((void*)args->stockid);
+ free((void*)args->icon);
+ free(args);
+}
+
+/* ---------------------------- UiToolbarToggleItemArgs ---------------------------- */
+
+UiToolbarToggleItemArgs* ui_toolbar_toggleitem_args_new(void) {
+ UiToolbarToggleItemArgs *args = malloc(sizeof(UiToolbarToggleItemArgs));
+ memset(args, 0, sizeof(UiToolbarToggleItemArgs));
+ return args;
+}
+
+
+void ui_toolbar_toggleitem_args_set_label(UiToolbarToggleItemArgs *args, const char *label) {
+ args->label = strdup(label);
+}
+
+
+void ui_toolbar_toggleitem_args_set_stockid(UiToolbarToggleItemArgs *args, const char *stockid) {
+ args->stockid = strdup(stockid);
+}
+
+
+void ui_toolbar_toggleitem_args_set_icon(UiToolbarToggleItemArgs *args, const char *icon) {
+ args->icon = strdup(icon);
+}
+
+
+void ui_toolbar_toggleitem_args_set_varname(UiToolbarToggleItemArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+
+void ui_toolbar_toggleitem_args_set_onchange(UiToolbarToggleItemArgs *args, ui_callback callback) {
+ args->onchange = callback;
+}
+
+
+void ui_toolbar_toggleitem_args_set_onchangedata(UiToolbarToggleItemArgs *args, void *onchangedata) {
+ args->onchangedata = onchangedata;
+}
+
+
+void ui_toolbar_toggleitem_args_set_groups(UiToolbarToggleItemArgs *args, int *groups) {
+ // TODO
+}
+
+
+void ui_toolbar_toggleitem_args_free(UiToolbarToggleItemArgs *args) {
+ free((void*)args->label);
+ free((void*)args->stockid);
+ free((void*)args->icon);
+ free((void*)args->varname);
+ free(args);
+}
+
+/* ---------------------------- UiToolbarMenuArgs ---------------------------- */
+
+
+UiToolbarMenuArgs* ui_toolbar_menu_args_new(void) {
+ UiToolbarMenuArgs *args = malloc(sizeof(UiToolbarMenuArgs));
+ memset(args, 0, sizeof(UiToolbarMenuArgs));
+ return args;
+}
+
+
+void ui_toolbar_menu_args_set_label(UiToolbarMenuArgs *args, const char *label) {
+ args->label = strdup(label);
+}
+
+
+void ui_toolbar_menu_args_set_stockid(UiToolbarMenuArgs *args, const char *stockid) {
+ args->stockid = strdup(stockid);
+}
+
+
+void ui_toolbar_menu_args_set_icon(UiToolbarMenuArgs *args, const char *icon) {
+ args->icon = strdup(icon);
+}
+
+
+void ui_toolbar_menu_args_free(UiToolbarMenuArgs *args) {
+ free((void*)args->label);
+ free((void*)args->stockid);
+ free((void*)args->icon);
+ free(args);
+}
+
+
+/* ---------------------------- UiContainerArgs ---------------------------- */
+
+UiContainerArgs* ui_container_args_new(void) {
+ UiContainerArgs *args = malloc(sizeof(UiContainerArgs));
+ memset(args, 0, sizeof(UiContainerArgs));
+ return args;
+}
+
+void ui_container_args_set_fill(UiContainerArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+void ui_container_args_set_hexpand(UiContainerArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_container_args_set_vexpand(UiContainerArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_container_args_set_hfill(UiContainerArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_container_args_set_vfill(UiContainerArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_container_args_set_override_defaults(UiContainerArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_container_args_set_colspan(UiContainerArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_container_args_set_rowspan(UiContainerArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_container_args_set_def_hexpand(UiContainerArgs *args, UiBool value) {
+ args->def_hexpand = value;
+}
+
+
+void ui_container_args_set_def_vexpand(UiContainerArgs *args, UiBool value) {
+ args->def_vexpand = value;
+}
+
+
+void ui_container_args_set_def_hfill(UiContainerArgs *args, UiBool value) {
+ args->def_hfill = value;
+}
+
+
+void ui_container_args_set_def_vfill(UiContainerArgs *args, UiBool value) {
+ args->def_vfill = value;
+}
+
+
+void ui_container_args_set_name(UiContainerArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_container_args_set_style_class(UiContainerArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+
+void ui_container_args_set_margin(UiContainerArgs *args, int value) {
+ args->margin = value;
+}
+
+
+void ui_container_args_set_spacing(UiContainerArgs *args, int value) {
+ args->spacing = value;
+}
+
+
+void ui_container_args_set_columnspacing(UiContainerArgs *args, int value) {
+ args->columnspacing = value;
+}
+
+
+void ui_container_args_set_rowspacing(UiContainerArgs *args, int value) {
+ args->rowspacing = value;
+}
+
+
+void ui_container_args_free(UiContainerArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free(args);
+}
+
+
+/* ------------------------------- UiFrameArgs ------------------------------*/
+
+UiFrameArgs* ui_frame_args_new(void) {
+ UiFrameArgs *args = malloc(sizeof(UiFrameArgs));
+ memset(args, 0, sizeof(UiContainerArgs));
+ return args;
+}
+
+
+void ui_frame_args_set_fill(UiFrameArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_frame_args_set_hexpand(UiFrameArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_frame_args_set_vexpand(UiFrameArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_frame_args_set_hfill(UiFrameArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_frame_args_set_vfill(UiFrameArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_frame_args_set_override_defaults(UiFrameArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_frame_args_set_colspan(UiFrameArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_frame_args_set_rowspan(UiFrameArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_frame_args_set_name(UiFrameArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_frame_args_set_style_class(UiFrameArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+
+void ui_frame_args_set_margin(UiFrameArgs *args, int value) {
+ args->margin = value;
+}
+
+
+void ui_frame_args_set_spacing(UiFrameArgs *args, int value) {
+ args->spacing = value;
+}
+
+
+void ui_frame_args_set_columnspacing(UiFrameArgs *args, int value) {
+ args->columnspacing = value;
+}
+
+
+void ui_frame_args_set_rowspacing(UiFrameArgs *args, int value) {
+ args->rowspacing = value;
+}
+
+
+void ui_frame_args_set_expanded(UiFrameArgs *args, UiBool value) {
+ args->isexpanded = value;
+}
+
+
+void ui_frame_args_set_label(UiFrameArgs *args, const char *label) {
+ args->label = strdup(label);
+}
+
+
+void ui_frame_args_free(UiFrameArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->label);
+ free(args);
+}
+
+
+/* ---------------------------- UiSidebarArgs -------------------------------*/
+
+UiSidebarArgs* ui_sidebar_args_new(void) {
+ UiSidebarArgs *args = malloc(sizeof(UiSidebarArgs));
+ memset(args, 0, sizeof(UiSidebarArgs));
+ return args;
+}
+
+
+void ui_sidebar_args_set_name(UiSidebarArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_sidebar_args_set_style_class(UiSidebarArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+
+void ui_sidebar_args_set_margin(UiSidebarArgs *args, int value) {
+ args->margin = value;
+}
+
+
+void ui_sidebar_args_set_spacing(UiSidebarArgs *args, int value) {
+ args->spacing = value;
+}
+
+
+void ui_sidebar_args_free(UiSidebarArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free(args);
+}
+
+
+/* --------------------------- UiSplitPaneArgs ------------------------------*/
+
+UiSplitPaneArgs* ui_splitpane_args_new(void) {
+ UiSplitPaneArgs *args = malloc(sizeof(UiSplitPaneArgs));
+ memset(args, 0, sizeof(UiSplitPaneArgs));
+ return args;
+}
+
+
+void ui_splitpane_args_set_fill(UiSplitPaneArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_splitpane_args_set_hexpand(UiSplitPaneArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_splitpane_args_set_vexpand(UiSplitPaneArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_splitpane_args_set_hfill(UiSplitPaneArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_splitpane_args_set_vfill(UiSplitPaneArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_splitpane_args_set_override_defaults(UiSplitPaneArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_splitpane_args_set_colspan(UiSplitPaneArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_splitpane_args_set_rowspan(UiSplitPaneArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_splitpane_args_set_name(UiSplitPaneArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_splitpane_args_set_style_class(UiSplitPaneArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+
+void ui_splitpane_args_set_margin(UiSplitPaneArgs *args, int value) {
+ args->margin = value;
+}
+
+
+void ui_splitpane_args_set_spacing(UiSplitPaneArgs *args, int value) {
+ args->spacing = value;
+}
+
+
+void ui_splitpane_args_set_columnspacing(UiSplitPaneArgs *args, int value) {
+ args->columnspacing = value;
+}
+
+
+void ui_splitpane_args_set_rowspacing(UiSplitPaneArgs *args, int value) {
+ args->rowspacing = value;
+}
+
+
+void ui_splitpane_args_set_initial_position(UiSplitPaneArgs *args, int pos) {
+ args->initial_position = pos;
+}
+
+
+void ui_splitpane_args_set_varname(UiSplitPaneArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+
+void ui_splitpane_args_set_value(UiSplitPaneArgs *args, UiInteger *value) {
+ args->value = value;
+}
+
+void ui_splitpane_args_set_max_panes(UiSplitPaneArgs *args, int max) {
+ args->max_panes = max;
+}
+
+
+void ui_splitpane_args_free(UiSplitPaneArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ free(args);
+}
+
+
+/* ------------------------- UiLabelArgs ----------------------------*/
+
+
+UiLabelArgs* ui_label_args_new(void) {
+ UiLabelArgs *args = malloc(sizeof(UiLabelArgs));
+ memset(args, 0, sizeof(UiLabelArgs));
+ return args;
+}
+
+
+void ui_label_args_set_fill(UiLabelArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_label_args_set_hexpand(UiLabelArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_label_args_set_vexpand(UiLabelArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_label_args_set_hfill(UiLabelArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_label_args_set_vfill(UiLabelArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_label_args_set_override_defaults(UiLabelArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_label_args_set_colspan(UiLabelArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_label_args_set_rowspan(UiLabelArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_label_args_set_name(UiLabelArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_label_args_set_style_class(UiLabelArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_label_args_set_label(UiLabelArgs *args, const char *label){
+ args->label = strdup(label);
+}
+
+
+void ui_label_args_set_align(UiLabelArgs *args, UiAlignment align) {
+ args->align = align;
+}
+
+void ui_label_args_set_style(UiLabelArgs *args, UiLabelStyle style) {
+ args->style = style;
+}
+
+void ui_label_args_set_varname(UiLabelArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_label_args_set_value(UiLabelArgs *args, UiString *value) {
+ args->value = value;
+}
+
+void ui_label_args_free(UiLabelArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->label);
+ free((void*)args->varname);
+ free(args);
+}
+
+
+/* ------------------------- UiProgressbarArgs ----------------------------*/
+
+
+UiProgressbarArgs* ui_progressbar_args_new(void) {
+ UiProgressbarArgs *args = malloc(sizeof(UiProgressbarArgs));
+ memset(args, 0, sizeof(UiProgressbarArgs));
+ return args;
+}
+
+
+void ui_progressbar_args_set_fill(UiProgressbarArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_progressbar_args_set_hexpand(UiProgressbarArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_progressbar_args_set_vexpand(UiProgressbarArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_progressbar_args_set_hfill(UiProgressbarArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_progressbar_args_set_vfill(UiProgressbarArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_progressbar_args_set_override_defaults(UiProgressbarArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_progressbar_args_set_colspan(UiProgressbarArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_progressbar_args_set_rowspan(UiProgressbarArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_progressbar_args_set_name(UiProgressbarArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_progressbar_args_set_style_class(UiProgressbarArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_progressbar_args_set_min(UiProgressbarArgs *args, double min) {
+ args->min = min;
+}
+
+void ui_progressbar_args_set_max(UiProgressbarArgs *args, double max) {
+ args->max = max;
+}
+
+void ui_progressbar_args_set_varname(UiProgressbarArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_progressbar_args_set_value(UiProgressbarArgs *args, UiDouble *value) {
+ args->value = value;
+}
+
+void ui_progressbar_args_free(UiProgressbarArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ free(args);
+}
+
+
+/* ------------------------- UiProgressbarSpinnerArgs ----------------------------*/
+
+UiProgressbarSpinnerArgs* ui_progress_spinner_args_new(void) {
+ UiProgressbarSpinnerArgs *args = malloc(sizeof(UiProgressbarSpinnerArgs));
+ memset(args, 0, sizeof(UiProgressbarSpinnerArgs));
+ return args;
+}
+
+void ui_progress_spinner_args_set_fill(UiProgressbarSpinnerArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+void ui_progress_spinner_args_set_hexpand(UiProgressbarSpinnerArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+void ui_progress_spinner_args_set_vexpand(UiProgressbarSpinnerArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+void ui_progress_spinner_args_set_hfill(UiProgressbarSpinnerArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+void ui_progress_spinner_args_set_vfill(UiProgressbarSpinnerArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+void ui_progress_spinner_args_set_override_defaults(UiProgressbarSpinnerArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+void ui_progress_spinner_args_set_colspan(UiProgressbarSpinnerArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+void ui_progress_spinner_args_set_rowspan(UiProgressbarSpinnerArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+void ui_progress_spinner_args_set_name(UiProgressbarSpinnerArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+void ui_progress_spinner_args_set_style_class(UiProgressbarSpinnerArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_progress_spinner_args_set_varname(UiProgressbarSpinnerArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_progress_spinner_args_set_value(UiProgressbarSpinnerArgs *args, UiInteger *value) {
+ args->value = value;
+}
+
+void ui_progress_spinner_args_free(UiProgressbarSpinnerArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ free(args);
+}
+
+
+/* ---------------------------- UiButtonArgs -------------------------------*/
+
+UiButtonArgs* ui_button_args_new(void) {
+ UiButtonArgs *args = malloc(sizeof(UiButtonArgs));
+ memset(args, 0, sizeof(UiButtonArgs));
+ return args;
+}
+
+
+void ui_button_args_set_fill(UiButtonArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_button_args_set_hexpand(UiButtonArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_button_args_set_vexpand(UiButtonArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_button_args_set_hfill(UiButtonArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_button_args_set_vfill(UiButtonArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_button_args_set_override_defaults(UiButtonArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_button_args_set_colspan(UiButtonArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_button_args_set_rowspan(UiButtonArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_button_args_set_name(UiButtonArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_button_args_set_style_class(UiButtonArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_button_args_set_label(UiButtonArgs *args, const char *label){
+ args->label = strdup(label);
+}
+
+
+void ui_button_args_set_stockid(UiButtonArgs *args, const char *stockid){
+ args->stockid = strdup(stockid);
+}
+
+
+void ui_button_args_set_icon(UiButtonArgs *args, const char *icon){
+ args->icon = strdup(icon);
+}
+
+
+void ui_button_args_set_labeltype(UiButtonArgs *args, int labeltype){
+ args->labeltype = labeltype;
+}
+
+void ui_button_args_set_onclick(UiButtonArgs *args, ui_callback callback){
+ args->onclick = callback;
+}
+
+
+void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata){
+ args->onclickdata = onclickdata;
+}
+
+void ui_button_args_set_groups(UiButtonArgs *args, int *groups){
+ // TODO
+}
+
+void ui_button_args_free(UiButtonArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->label);
+ free((void*)args->stockid);
+ free((void*)args->icon);
+ free((void*)args->groups);
+ free(args);
+}
+
+
+/* ------------------------- UiToggleArgs ----------------------------*/
+
+
+UiToggleArgs* ui_toggle_args_new(void) {
+ UiToggleArgs *args = malloc(sizeof(UiToggleArgs));
+ memset(args, 0, sizeof(UiToggleArgs));
+ return args;
+}
+
+
+void ui_toggle_args_set_fill(UiToggleArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_toggle_args_set_hexpand(UiToggleArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_toggle_args_set_vexpand(UiToggleArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_toggle_args_set_hfill(UiToggleArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_toggle_args_set_vfill(UiToggleArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_toggle_args_set_override_defaults(UiToggleArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_toggle_args_set_colspan(UiToggleArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_toggle_args_set_rowspan(UiToggleArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_toggle_args_set_name(UiToggleArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_toggle_args_set_style_class(UiToggleArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_toggle_args_set_label(UiToggleArgs *args, const char *label){
+ args->label = strdup(label);
+}
+
+
+void ui_toggle_args_set_stockid(UiToggleArgs *args, const char *stockid){
+ args->stockid = strdup(stockid);
+}
+
+
+void ui_toggle_args_set_icon(UiToggleArgs *args, const char *icon){
+ args->icon = strdup(icon);
+}
+
+
+void ui_toggle_args_set_labeltype(UiToggleArgs *args, int labeltype){
+ args->labeltype = labeltype;
+}
+
+void ui_toggle_args_set_onchange(UiToggleArgs *args, ui_callback callback){
+ args->onchange = callback;
+}
+
+
+void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata){
+ args->onchangedata = onchangedata;
+}
+
+void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_toggle_args_set_value(UiToggleArgs *args, UiInteger *value) {
+ args->value = value;
+}
+
+void ui_toggle_args_set_enablegroup(UiToggleArgs *args, int group) {
+ args->enable_group = group;
+}
+
+void ui_toggle_args_set_groups(UiToggleArgs *args, int *groups){
+ // TODO
+}
+
+void ui_toggle_args_free(UiToggleArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->label);
+ free((void*)args->stockid);
+ free((void*)args->icon);
+ free((void*)args->varname);
+ free((void*)args->groups);
+ free(args);
+}
+
+
+/* ------------------------- UiListArgs ----------------------------*/
+
+UiListArgs* ui_list_args_new(void) {
+ UiListArgs *args = malloc(sizeof(UiListArgs));
+ memset(args, 0, sizeof(UiListArgs));
+ return args;
+}
+
+void ui_list_args_set_fill(UiListArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+void ui_list_args_set_hexpand(UiListArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+void ui_list_args_set_vexpand(UiListArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+void ui_list_args_set_hfill(UiListArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+void ui_list_args_set_vfill(UiListArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+void ui_list_args_set_override_defaults(UiListArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+void ui_list_args_set_colspan(UiListArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+void ui_list_args_set_rowspan(UiListArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+void ui_list_args_set_name(UiListArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+void ui_list_args_set_style_class(UiListArgs *args, const char *classname) {
+ args->style_class = classname;
+}
+
+void ui_list_args_set_varname(UiListArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_list_args_set_value(UiListArgs *args, UiList *value) {
+ args->list = value;
+}
+
+void ui_list_args_set_model(UiListArgs *args, UiModel *model) {
+ args->model = model;
+}
+
+void ui_list_args_set_static_elements(UiListArgs *args, char **strarray, size_t nelm) {
+ char **array = calloc(nelm, sizeof(char*));
+ for(int i=0;istatic_elements = array;
+ args->static_nelm = nelm;
+}
+
+void ui_list_args_set_getvalue_func(UiListArgs *args, ui_getvaluefunc getvalue) {
+ args->getvalue = getvalue;
+}
+
+void ui_list_args_set_getvalue_func2(UiListArgs *args, ui_getvaluefunc2 getvalue) {
+ args->getvalue2 = getvalue;
+}
+
+void ui_list_args_set_getvalue_data(UiListArgs *args, void *userdata) {
+ args->getvalue2data = userdata;
+}
+
+void ui_list_args_set_onactivate(UiListArgs *args, ui_callback callback) {
+ args->onactivate = callback;
+}
+
+void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata) {
+ args->onactivatedata = userdata;
+}
+
+void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback) {
+ args->onselection = callback;
+}
+
+void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata) {
+ args->onselectiondata = userdata;
+}
+
+void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback) {
+ args->ondragstart = callback;
+}
+
+void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata) {
+ args->ondragstartdata = userdata;
+}
+
+void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback) {
+ args->ondragcomplete = callback;
+}
+
+void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata) {
+ args->ondragcompletedata = userdata;
+}
+
+void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback) {
+ args->ondrop = callback;
+}
+
+void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata) {
+ args->ondropdata = userdata;
+}
+
+void ui_list_args_set_multiselection(UiListArgs *args, UiBool multiselection) {
+ args->multiselection = multiselection;
+}
+
+void ui_list_args_set_contextmenu(UiListArgs *args, UiMenuBuilder *menubuilder) {
+ args->contextmenu = menubuilder;
+}
+
+void ui_list_args_set_groups(UiListArgs *args, int *groups) {
+ // TODO
+}
+
+void ui_list_args_free(UiListArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ if(args->static_elements) {
+ for(int i=0;istatic_nelm;i++) {
+ free(args->static_elements[i]);
+ }
+ free(args->static_elements);
+ }
+ free(args);
+}
+
+
+
+/* ---------------------- SurceList ------------------------------------- */
+
+UiSourceListArgs* ui_sourcelist_args_new(void) {
+ UiSourceListArgs *args = malloc(sizeof(UiSourceListArgs));
+ memset(args, 0, sizeof(UiSourceListArgs));
+ return args;
+}
+
+
+void ui_sourcelist_args_set_fill(UiSourceListArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_sourcelist_args_set_hexpand(UiSourceListArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_sourcelist_args_set_vexpand(UiSourceListArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_sourcelist_args_set_hfill(UiSourceListArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_sourcelist_args_set_vfill(UiSourceListArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_sourcelist_args_set_override_defaults(UiSourceListArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_sourcelist_args_set_colspan(UiSourceListArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_sourcelist_args_set_rowspan(UiSourceListArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_sourcelist_args_set_name(UiSourceListArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_sourcelist_args_set_style_class(UiSourceListArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+UIEXPORT void ui_sourcelist_args_set_static_sublists(UiSourceListArgs *args, UiSubList *sublists, size_t numsublists) {
+ args->sublists = calloc(numsublists, sizeof(UiSubList));
+ memcpy(args->sublists, sublists, numsublists * sizeof(UiSubList));
+ args->numsublists = numsublists;
+}
+
+void ui_sourcelist_args_set_varname(UiSourceListArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+
+void ui_sourcelist_args_set_dynamic_sublists(UiSourceListArgs *args, UiList *value) {
+ args->dynamic_sublist = value;
+}
+
+
+void ui_sourcelist_args_set_getvalue_func(UiSourceListArgs *args, ui_sublist_getvalue_func getvalue) {
+ args->getvalue = getvalue;
+}
+
+void ui_sourcelist_args_set_getvalue_userdata(UiSourceListArgs *args, void *userdata) {
+ args->getvaluedata = userdata;
+}
+
+void ui_sourcelist_args_set_onactivate(UiSourceListArgs *args, ui_callback callback) {
+ args->onactivate = callback;
+}
+
+
+void ui_sourcelist_args_set_onactivatedata(UiSourceListArgs *args, void *userdata) {
+ args->onactivatedata = userdata;
+}
+
+
+void ui_sourcelist_args_set_onbuttonclick(UiSourceListArgs *args, ui_callback callback) {
+ args->onbuttonclick = callback;
+
+}
+
+
+void ui_sourcelist_args_set_onbuttonclickdata(UiSourceListArgs *args, void *userdata) {
+ args->onbuttonclickdata = userdata;
+}
+
+
+void ui_sourcelist_args_free(UiSourceListArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ free((void*)args->sublists);
+ free(args);
+}
+
+
+/* ------------------------- UiTextAreaArgs ----------------------------*/
+
+UiTextAreaArgs* ui_textarea_args_new(void) {
+ UiTextAreaArgs *args = malloc(sizeof(UiTextAreaArgs));
+ memset(args, 0, sizeof(UiTextAreaArgs));
+ return args;
+}
+
+
+void ui_textarea_args_set_fill(UiTextAreaArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_textarea_args_set_hexpand(UiTextAreaArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_textarea_args_set_vexpand(UiTextAreaArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_textarea_args_set_hfill(UiTextAreaArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_textarea_args_set_vfill(UiTextAreaArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_textarea_args_set_override_defaults(UiTextAreaArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_textarea_args_set_colspan(UiTextAreaArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_textarea_args_set_rowspan(UiTextAreaArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_textarea_args_set_name(UiTextAreaArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_textarea_args_set_style_class(UiTextAreaArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_textarea_args_set_onchange(UiTextAreaArgs *args, ui_callback callback){
+ args->onchange = callback;
+}
+
+
+void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata){
+ args->onchangedata = onchangedata;
+}
+
+void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_textarea_args_set_value(UiTextAreaArgs *args, UiText *value) {
+ args->value = value;
+}
+
+void ui_textarea_args_set_groups(UiTextAreaArgs *args, int *groups){
+ // TODO
+}
+
+void ui_textarea_args_free(UiTextAreaArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ free((void*)args->groups);
+ free(args);
+}
+
+
+
+/* ------------------------- UiTextFieldArgs ----------------------------*/
+
+UiTextFieldArgs* ui_textfield_args_new(void) {
+ UiTextFieldArgs *args = malloc(sizeof(UiTextFieldArgs));
+ memset(args, 0, sizeof(UiTextFieldArgs));
+ return args;
+}
+
+
+void ui_textfield_args_set_fill(UiTextFieldArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_textfield_args_set_hexpand(UiTextFieldArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_textfield_args_set_vexpand(UiTextFieldArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_textfield_args_set_hfill(UiTextFieldArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_textfield_args_set_vfill(UiTextFieldArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_textfield_args_set_override_defaults(UiTextFieldArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_textfield_args_set_colspan(UiTextFieldArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_textfield_args_set_rowspan(UiTextFieldArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_textfield_args_set_name(UiTextFieldArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_textfield_args_set_style_class(UiTextFieldArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_textfield_args_set_onchange(UiTextFieldArgs *args, ui_callback callback){
+ args->onchange = callback;
+}
+
+
+void ui_textfield_args_set_onchangedata(UiTextFieldArgs *args, void *onchangedata){
+ args->onchangedata = onchangedata;
+}
+
+void ui_textfield_args_set_onactivate(UiTextFieldArgs *args, ui_callback callback){
+ args->onactivate = callback;
+}
+
+
+void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivatedata){
+ args->onactivatedata = onactivatedata;
+}
+
+void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_textfield_args_set_value(UiTextFieldArgs *args, UiString *value) {
+ args->value = value;
+}
+
+void ui_textfield_args_set_groups(UiTextFieldArgs *args, int *groups){
+ // TODO
+}
+
+void ui_textfield_args_free(UiTextFieldArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ free((void*)args->groups);
+ free(args);
+}
+
+
+/* ------------------------- UiWebviewArgs ----------------------------*/
+
+UiWebviewArgs* ui_webview_args_new(void) {
+ UiWebviewArgs *args = malloc(sizeof(UiWebviewArgs));
+ memset(args, 0, sizeof(UiWebviewArgs));
+ return args;
+}
+
+
+void ui_webview_args_set_fill(UiWebviewArgs *args, UiBool fill) {
+ args->fill = fill ? UI_ON : UI_OFF;
+}
+
+
+void ui_webview_args_set_hexpand(UiWebviewArgs *args, UiBool value) {
+ args->hexpand = value;
+}
+
+
+void ui_webview_args_set_vexpand(UiWebviewArgs *args, UiBool value) {
+ args->vexpand = value;
+}
+
+
+void ui_webview_args_set_hfill(UiWebviewArgs *args, UiBool value) {
+ args->hfill = value;
+}
+
+
+void ui_webview_args_set_vfill(UiWebviewArgs *args, UiBool value) {
+ args->vfill = value;
+}
+
+
+void ui_webview_args_set_override_defaults(UiWebviewArgs *args, UiBool value) {
+ args->override_defaults = value;
+}
+
+
+void ui_webview_args_set_colspan(UiWebviewArgs *args, int colspan) {
+ args->colspan = colspan;
+}
+
+
+void ui_webview_args_set_rowspan(UiWebviewArgs *args, int rowspan) {
+ args->rowspan = rowspan;
+}
+
+
+void ui_webview_args_set_name(UiWebviewArgs *args, const char *name) {
+ args->name = strdup(name);
+}
+
+
+void ui_webview_args_set_style_class(UiWebviewArgs *args, const char *classname) {
+ args->style_class = strdup(classname);
+}
+
+void ui_webview_args_set_varname(UiWebviewArgs *args, const char *varname) {
+ args->varname = strdup(varname);
+}
+
+void ui_webview_args_set_value(UiWebviewArgs *args, UiGeneric *value) {
+ args->value = value;
+}
+
+void ui_webview_args_set_groups(UiWebviewArgs *args, int *groups){
+ // TODO
+}
+
+void ui_webview_args_free(UiWebviewArgs *args) {
+ free((void*)args->name);
+ free((void*)args->style_class);
+ free((void*)args->varname);
+ free((void*)args->groups);
+ free(args);
+}
+
diff --git a/ui/common/args.h b/ui/common/args.h
new file mode 100644
index 0000000..04e7063
--- /dev/null
+++ b/ui/common/args.h
@@ -0,0 +1,372 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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.
+ */
+
+#ifndef UIC_ARGS_H
+#define UIC_ARGS_H
+
+#include "../ui/container.h"
+#include "../ui/display.h"
+#include "../ui/button.h"
+#include "../ui/menu.h"
+#include "../ui/toolbar.h"
+#include "../ui/tree.h"
+#include "../ui/text.h"
+#include "../ui/webview.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+UIEXPORT UiMenuItemArgs* ui_menuitem_args_new(void);
+UIEXPORT void ui_menuitem_args_set_label(UiMenuItemArgs *args, const char *label);
+UIEXPORT void ui_menuitem_args_set_stockid(UiMenuItemArgs *args, const char *stockid);
+UIEXPORT void ui_menuitem_args_set_icon(UiMenuItemArgs *args, const char *icon);
+UIEXPORT void ui_menuitem_args_set_onclick(UiMenuItemArgs *args, ui_callback callback);
+UIEXPORT void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata);
+UIEXPORT void ui_menuitem_args_free(UiMenuItemArgs *args);
+
+UIEXPORT UiMenuToggleItemArgs* ui_menutoggleitem_args_new(void);
+UIEXPORT void ui_menutoggleitem_args_set_label(UiMenuToggleItemArgs *args, const char *label);
+UIEXPORT void ui_menutoggleitem_args_set_stockid(UiMenuToggleItemArgs *args, const char *stockid);
+UIEXPORT void ui_menutoggleitem_args_set_icon(UiMenuToggleItemArgs *args, const char *icon);
+UIEXPORT void ui_menutoggleitem_args_set_varname(UiMenuToggleItemArgs *args, const char *varname);
+UIEXPORT void ui_menutoggleitem_args_set_onchange(UiMenuToggleItemArgs *args, ui_callback callback);
+UIEXPORT void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *onchangedata);
+UIEXPORT void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args);
+
+UIEXPORT UiMenuItemListArgs* ui_menuitemlist_args_new(void);
+UIEXPORT void ui_menuitemlist_args_set_varname(UiMenuItemListArgs *args, const char *varname);
+UIEXPORT void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc func);
+UIEXPORT void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback);
+UIEXPORT void ui_menuitemlist_args_set_onselectdata(UiMenuItemListArgs *args, void *data);
+UIEXPORT void ui_menuitemlist_args_set_addseparator(UiMenuItemListArgs *args, UiBool value);
+UIEXPORT void ui_menuitemlist_args_free(UiMenuItemListArgs *args);
+
+UIEXPORT UiToolbarItemArgs* ui_toolbar_item_args_new(void);
+UIEXPORT void ui_toolbar_item_args_set_label(UiToolbarItemArgs *args, const char *label);
+UIEXPORT void ui_toolbar_item_args_set_stockid(UiToolbarItemArgs *args, const char *stockid);
+UIEXPORT void ui_toolbar_item_args_set_icon(UiToolbarItemArgs *args, const char *icon);
+UIEXPORT void ui_toolbar_item_args_set_onclick(UiToolbarItemArgs *args, ui_callback callback);
+UIEXPORT void ui_toolbar_item_args_set_onclickdata(UiToolbarItemArgs *args, void *onclickdata);
+UIEXPORT void ui_toolbar_item_args_set_groups(UiToolbarItemArgs *args, int *groups);
+UIEXPORT void ui_toolbar_item_args_free(UiToolbarItemArgs *args);
+
+UIEXPORT UiToolbarToggleItemArgs* ui_toolbar_toggleitem_args_new(void);
+UIEXPORT void ui_toolbar_toggleitem_args_set_label(UiToolbarToggleItemArgs *args, const char *label);
+UIEXPORT void ui_toolbar_toggleitem_args_set_stockid(UiToolbarToggleItemArgs *args, const char *stockid);
+UIEXPORT void ui_toolbar_toggleitem_args_set_icon(UiToolbarToggleItemArgs *args, const char *icon);
+UIEXPORT void ui_toolbar_toggleitem_args_set_varname(UiToolbarToggleItemArgs *args, const char *varname);
+UIEXPORT void ui_toolbar_toggleitem_args_set_onchange(UiToolbarToggleItemArgs *args, ui_callback callback);
+UIEXPORT void ui_toolbar_toggleitem_args_set_onchangedata(UiToolbarToggleItemArgs *args, void *onchangedata);
+UIEXPORT void ui_toolbar_toggleitem_args_set_groups(UiToolbarToggleItemArgs *args, int *groups);
+UIEXPORT void ui_toolbar_toggleitem_args_free(UiToolbarToggleItemArgs *args);
+
+UIEXPORT UiToolbarMenuArgs* ui_toolbar_menu_args_new(void);
+UIEXPORT void ui_toolbar_menu_args_set_label(UiToolbarMenuArgs *args, const char *label);
+UIEXPORT void ui_toolbar_menu_args_set_stockid(UiToolbarMenuArgs *args, const char *stockid);
+UIEXPORT void ui_toolbar_menu_args_set_icon(UiToolbarMenuArgs *args, const char *icon);
+UIEXPORT void ui_toolbar_menu_args_free(UiToolbarMenuArgs *args);
+
+UIEXPORT UiContainerArgs* ui_container_args_new(void);
+UIEXPORT void ui_container_args_set_fill(UiContainerArgs *args, UiBool fill);
+UIEXPORT void ui_container_args_set_hexpand(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_vexpand(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_hfill(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_vfill(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_override_defaults(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_colspan(UiContainerArgs *args, int colspan);
+UIEXPORT void ui_container_args_set_rowspan(UiContainerArgs *args, int rowspan);
+UIEXPORT void ui_container_args_set_def_hexpand(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_def_vexpand(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_def_hfill(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_def_vfill(UiContainerArgs *args, UiBool value);
+UIEXPORT void ui_container_args_set_name(UiContainerArgs *args, const char *name);
+UIEXPORT void ui_container_args_set_style_class(UiContainerArgs *args, const char *classname);
+UIEXPORT void ui_container_args_set_margin(UiContainerArgs *args, int value);
+UIEXPORT void ui_container_args_set_spacing(UiContainerArgs *args, int value);
+UIEXPORT void ui_container_args_set_columnspacing(UiContainerArgs *args, int value);
+UIEXPORT void ui_container_args_set_rowspacing(UiContainerArgs *args, int value);
+UIEXPORT void ui_container_args_free(UiContainerArgs *args);
+
+
+UIEXPORT UiFrameArgs* ui_frame_args_new(void);
+UIEXPORT void ui_frame_args_set_fill(UiFrameArgs *args, UiBool fill);
+UIEXPORT void ui_frame_args_set_hexpand(UiFrameArgs *args, UiBool value);
+UIEXPORT void ui_frame_args_set_vexpand(UiFrameArgs *args, UiBool value);
+UIEXPORT void ui_frame_args_set_hfill(UiFrameArgs *args, UiBool value);
+UIEXPORT void ui_frame_args_set_vfill(UiFrameArgs *args, UiBool value);
+UIEXPORT void ui_frame_args_set_override_defaults(UiFrameArgs *args, UiBool value);
+UIEXPORT void ui_frame_args_set_colspan(UiFrameArgs *args, int colspan);
+UIEXPORT void ui_frame_args_set_rowspan(UiFrameArgs *args, int rowspan);
+UIEXPORT void ui_frame_args_set_name(UiFrameArgs *args, const char *name);
+UIEXPORT void ui_frame_args_set_style_class(UiFrameArgs *args, const char *classname);
+UIEXPORT void ui_frame_args_set_margin(UiFrameArgs *args, int value);
+UIEXPORT void ui_frame_args_set_spacing(UiFrameArgs *args, int value);
+UIEXPORT void ui_frame_args_set_columnspacing(UiFrameArgs *args, int value);
+UIEXPORT void ui_frame_args_set_rowspacing(UiFrameArgs *args, int value);
+UIEXPORT void ui_frame_args_set_expanded(UiFrameArgs *args, UiBool value);
+UIEXPORT void ui_frame_args_set_label(UiFrameArgs *args, const char *label);
+UIEXPORT void ui_frame_args_free(UiFrameArgs *args);
+
+UIEXPORT UiSidebarArgs* ui_sidebar_args_new(void);
+UIEXPORT void ui_sidebar_args_set_name(UiSidebarArgs *args, const char *name);
+UIEXPORT void ui_sidebar_args_set_style_class(UiSidebarArgs *args, const char *classname);
+UIEXPORT void ui_sidebar_args_set_margin(UiSidebarArgs *args, int value);
+UIEXPORT void ui_sidebar_args_set_spacing(UiSidebarArgs *args, int value);
+UIEXPORT void ui_sidebar_args_free(UiSidebarArgs *args);
+
+UIEXPORT UiSplitPaneArgs* ui_splitpane_args_new(void);
+UIEXPORT void ui_splitpane_args_set_fill(UiSplitPaneArgs *args, UiBool fill);
+UIEXPORT void ui_splitpane_args_set_hexpand(UiSplitPaneArgs *args, UiBool value);
+UIEXPORT void ui_splitpane_args_set_vexpand(UiSplitPaneArgs *args, UiBool value);
+UIEXPORT void ui_splitpane_args_set_hfill(UiSplitPaneArgs *args, UiBool value);
+UIEXPORT void ui_splitpane_args_set_vfill(UiSplitPaneArgs *args, UiBool value);
+UIEXPORT void ui_splitpane_args_set_override_defaults(UiSplitPaneArgs *args, UiBool value);
+UIEXPORT void ui_splitpane_args_set_colspan(UiSplitPaneArgs *args, int colspan);
+UIEXPORT void ui_splitpane_args_set_rowspan(UiSplitPaneArgs *args, int rowspan);
+UIEXPORT void ui_splitpane_args_set_name(UiSplitPaneArgs *args, const char *name);
+UIEXPORT void ui_splitpane_args_set_style_class(UiSplitPaneArgs *args, const char *classname);
+UIEXPORT void ui_splitpane_args_set_margin(UiSplitPaneArgs *args, int value);
+UIEXPORT void ui_splitpane_args_set_spacing(UiSplitPaneArgs *args, int value);
+UIEXPORT void ui_splitpane_args_set_columnspacing(UiSplitPaneArgs *args, int value);
+UIEXPORT void ui_splitpane_args_set_rowspacing(UiSplitPaneArgs *args, int value);
+UIEXPORT void ui_splitpane_args_set_initial_position(UiSplitPaneArgs *args, int pos);
+UIEXPORT void ui_splitpane_args_set_varname(UiSplitPaneArgs *args, const char *varname);
+UIEXPORT void ui_splitpane_args_set_value(UiSplitPaneArgs *args, UiInteger *value);
+UIEXPORT void ui_splitpane_args_set_max_panes(UiSplitPaneArgs *args, int max);
+UIEXPORT void ui_splitpane_args_free(UiSplitPaneArgs *args);
+
+UIEXPORT UiLabelArgs* ui_label_args_new(void);
+UIEXPORT void ui_label_args_set_fill(UiLabelArgs *args, UiBool fill);
+UIEXPORT void ui_label_args_set_hexpand(UiLabelArgs *args, UiBool value);
+UIEXPORT void ui_label_args_set_vexpand(UiLabelArgs *args, UiBool value);
+UIEXPORT void ui_label_args_set_hfill(UiLabelArgs *args, UiBool value);
+UIEXPORT void ui_label_args_set_vfill(UiLabelArgs *args, UiBool value);
+UIEXPORT void ui_label_args_set_override_defaults(UiLabelArgs *args, UiBool value);
+UIEXPORT void ui_label_args_set_colspan(UiLabelArgs *args, int colspan);
+UIEXPORT void ui_label_args_set_rowspan(UiLabelArgs *args, int rowspan);
+UIEXPORT void ui_label_args_set_name(UiLabelArgs *args, const char *name);
+UIEXPORT void ui_label_args_set_style_class(UiLabelArgs *args, const char *classname);
+UIEXPORT void ui_label_args_set_label(UiLabelArgs *args, const char *label);
+UIEXPORT void ui_label_args_set_align(UiLabelArgs *args, UiAlignment align);
+UIEXPORT void ui_label_args_set_style(UiLabelArgs *args, UiLabelStyle style);
+UIEXPORT void ui_label_args_set_value(UiLabelArgs *args, UiString *value);
+UIEXPORT void ui_label_args_set_varname(UiLabelArgs *args, const char *varname);
+UIEXPORT void ui_label_args_free(UiLabelArgs *args);
+
+UIEXPORT UiProgressbarArgs* ui_progressbar_args_new(void);
+UIEXPORT void ui_progressbar_args_set_fill(UiProgressbarArgs *args, UiBool fill);
+UIEXPORT void ui_progressbar_args_set_hexpand(UiProgressbarArgs *args, UiBool value);
+UIEXPORT void ui_progressbar_args_set_vexpand(UiProgressbarArgs *args, UiBool value);
+UIEXPORT void ui_progressbar_args_set_hfill(UiProgressbarArgs *args, UiBool value);
+UIEXPORT void ui_progressbar_args_set_vfill(UiProgressbarArgs *args, UiBool value);
+UIEXPORT void ui_progressbar_args_set_override_defaults(UiProgressbarArgs *args, UiBool value);
+UIEXPORT void ui_progressbar_args_set_colspan(UiProgressbarArgs *args, int colspan);
+UIEXPORT void ui_progressbar_args_set_rowspan(UiProgressbarArgs *args, int rowspan);
+UIEXPORT void ui_progressbar_args_set_name(UiProgressbarArgs *args, const char *name);
+UIEXPORT void ui_progressbar_args_set_style_class(UiProgressbarArgs *args, const char *classname);
+UIEXPORT void ui_progressbar_args_set_min(UiProgressbarArgs *args, double min);
+UIEXPORT void ui_progressbar_args_set_max(UiProgressbarArgs *args, double max);
+UIEXPORT void ui_progressbar_args_set_value(UiProgressbarArgs *args, UiDouble *value);
+UIEXPORT void ui_progressbar_args_set_varname(UiProgressbarArgs *args, const char *varname);
+UIEXPORT void ui_progressbar_args_free(UiProgressbarArgs *args);
+
+UIEXPORT UiProgressbarSpinnerArgs* ui_progress_spinner_args_new(void);
+UIEXPORT void ui_progress_spinner_args_set_fill(UiProgressbarSpinnerArgs *args, UiBool fill);
+UIEXPORT void ui_progress_spinner_args_set_hexpand(UiProgressbarSpinnerArgs *args, UiBool value);
+UIEXPORT void ui_progress_spinner_args_set_vexpand(UiProgressbarSpinnerArgs *args, UiBool value);
+UIEXPORT void ui_progress_spinner_args_set_hfill(UiProgressbarSpinnerArgs *args, UiBool value);
+UIEXPORT void ui_progress_spinner_args_set_vfill(UiProgressbarSpinnerArgs *args, UiBool value);
+UIEXPORT void ui_progress_spinner_args_set_override_defaults(UiProgressbarSpinnerArgs *args, UiBool value);
+UIEXPORT void ui_progress_spinner_args_set_colspan(UiProgressbarSpinnerArgs *args, int colspan);
+UIEXPORT void ui_progress_spinner_args_set_rowspan(UiProgressbarSpinnerArgs *args, int rowspan);
+UIEXPORT void ui_progress_spinner_args_set_name(UiProgressbarSpinnerArgs *args, const char *name);
+UIEXPORT void ui_progress_spinner_args_set_style_class(UiProgressbarSpinnerArgs *args, const char *classname);
+UIEXPORT void ui_progress_spinner_args_set_value(UiProgressbarSpinnerArgs *args, UiInteger *value);
+UIEXPORT void ui_progress_spinner_args_set_varname(UiProgressbarSpinnerArgs *args, const char *varname);
+UIEXPORT void ui_progress_spinner_args_free(UiProgressbarSpinnerArgs *args);
+
+UIEXPORT UiButtonArgs* ui_button_args_new(void);
+UIEXPORT void ui_button_args_set_fill(UiButtonArgs *args, UiBool fill);
+UIEXPORT void ui_button_args_set_hexpand(UiButtonArgs *args, UiBool value);
+UIEXPORT void ui_button_args_set_vexpand(UiButtonArgs *args, UiBool value);
+UIEXPORT void ui_button_args_set_hfill(UiButtonArgs *args, UiBool value);
+UIEXPORT void ui_button_args_set_vfill(UiButtonArgs *args, UiBool value);
+UIEXPORT void ui_button_args_set_override_defaults(UiButtonArgs *args, UiBool value);
+UIEXPORT void ui_button_args_set_colspan(UiButtonArgs *args, int colspan);
+UIEXPORT void ui_button_args_set_rowspan(UiButtonArgs *args, int rowspan);
+UIEXPORT void ui_button_args_set_name(UiButtonArgs *args, const char *name);
+UIEXPORT void ui_button_args_set_style_class(UiButtonArgs *args, const char *classname);
+UIEXPORT void ui_button_args_set_label(UiButtonArgs *args, const char *label);
+UIEXPORT void ui_button_args_set_stockid(UiButtonArgs *args, const char *stockid);
+UIEXPORT void ui_button_args_set_icon(UiButtonArgs *args, const char *icon);
+UIEXPORT void ui_button_args_set_labeltype(UiButtonArgs *args, int labeltype);
+UIEXPORT void ui_button_args_set_onclick(UiButtonArgs *args, ui_callback callback);
+UIEXPORT void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata);
+UIEXPORT void ui_button_args_set_groups(UiButtonArgs *args, int *groups);
+UIEXPORT void ui_button_args_free(UiButtonArgs *args);
+
+UIEXPORT UiToggleArgs* ui_toggle_args_new(void);
+UIEXPORT void ui_toggle_args_set_fill(UiToggleArgs *args, UiBool fill);
+UIEXPORT void ui_toggle_args_set_hexpand(UiToggleArgs *args, UiBool value);
+UIEXPORT void ui_toggle_args_set_vexpand(UiToggleArgs *args, UiBool value);
+UIEXPORT void ui_toggle_args_set_hfill(UiToggleArgs *args, UiBool value);
+UIEXPORT void ui_toggle_args_set_vfill(UiToggleArgs *args, UiBool value);
+UIEXPORT void ui_toggle_args_set_override_defaults(UiToggleArgs *args, UiBool value);
+UIEXPORT void ui_toggle_args_set_colspan(UiToggleArgs *args, int colspan);
+UIEXPORT void ui_toggle_args_set_rowspan(UiToggleArgs *args, int rowspan);
+UIEXPORT void ui_toggle_args_set_name(UiToggleArgs *args, const char *name);
+UIEXPORT void ui_toggle_args_set_style_class(UiToggleArgs *args, const char *classname);
+UIEXPORT void ui_toggle_args_set_label(UiToggleArgs *args, const char *label);
+UIEXPORT void ui_toggle_args_set_stockid(UiToggleArgs *args, const char *stockid);
+UIEXPORT void ui_toggle_args_set_icon(UiToggleArgs *args, const char *icon);
+UIEXPORT void ui_toggle_args_set_labeltype(UiToggleArgs *args, int labeltype);
+UIEXPORT void ui_toggle_args_set_onchange(UiToggleArgs *args, ui_callback callback);
+UIEXPORT void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata);
+UIEXPORT void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname);
+UIEXPORT void ui_toggle_args_set_value(UiToggleArgs *args, UiInteger *value);
+UIEXPORT void ui_toggle_args_set_enablegroup(UiToggleArgs *args, int group);
+UIEXPORT void ui_toggle_args_set_groups(UiToggleArgs *args, int *groups);
+UIEXPORT void ui_toggle_args_free(UiToggleArgs *args);
+
+UIEXPORT UiListArgs* ui_list_args_new(void);
+UIEXPORT void ui_list_args_set_fill(UiListArgs *args, UiBool fill);
+UIEXPORT void ui_list_args_set_hexpand(UiListArgs *args, UiBool value);
+UIEXPORT void ui_list_args_set_vexpand(UiListArgs *args, UiBool value);
+UIEXPORT void ui_list_args_set_hfill(UiListArgs *args, UiBool value);
+UIEXPORT void ui_list_args_set_vfill(UiListArgs *args, UiBool value);
+UIEXPORT void ui_list_args_set_override_defaults(UiListArgs *args, UiBool value);
+UIEXPORT void ui_list_args_set_colspan(UiListArgs *args, int colspan);
+UIEXPORT void ui_list_args_set_rowspan(UiListArgs *args, int rowspan);
+UIEXPORT void ui_list_args_set_name(UiListArgs *args, const char *name);
+UIEXPORT void ui_list_args_set_style_class(UiListArgs *args, const char *classname);
+UIEXPORT void ui_list_args_set_varname(UiListArgs *args, const char *varname);
+UIEXPORT void ui_list_args_set_value(UiListArgs *args, UiList *value);
+UIEXPORT void ui_list_args_set_model(UiListArgs *args, UiModel *model);
+UIEXPORT void ui_list_args_set_static_elements(UiListArgs *args, char **strarray, size_t nelm);
+UIEXPORT void ui_list_args_set_getvalue_func(UiListArgs *args, ui_getvaluefunc getvalue);
+UIEXPORT void ui_list_args_set_getvalue_func2(UiListArgs *args, ui_getvaluefunc2 getvalue);
+UIEXPORT void ui_list_args_set_getvalue_data(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onactivate(UiListArgs *args, ui_callback callback);
+UIEXPORT void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback);
+UIEXPORT void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback);
+UIEXPORT void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback);
+UIEXPORT void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback);
+UIEXPORT void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_multiselection(UiListArgs *args, UiBool multiselection);
+UIEXPORT void ui_list_args_set_contextmenu(UiListArgs *args, UiMenuBuilder *menubuilder);
+UIEXPORT void ui_list_args_set_groups(UiListArgs *args, int *groups);
+UIEXPORT void ui_list_args_free(UiListArgs *args);
+
+UIEXPORT UiSourceListArgs* ui_sourcelist_args_new(void);
+UIEXPORT void ui_sourcelist_args_set_fill(UiSourceListArgs *args, UiBool fill);
+UIEXPORT void ui_sourcelist_args_set_hexpand(UiSourceListArgs *args, UiBool value);
+UIEXPORT void ui_sourcelist_args_set_vexpand(UiSourceListArgs *args, UiBool value);
+UIEXPORT void ui_sourcelist_args_set_hfill(UiSourceListArgs *args, UiBool value);
+UIEXPORT void ui_sourcelist_args_set_vfill(UiSourceListArgs *args, UiBool value);
+UIEXPORT void ui_sourcelist_args_set_override_defaults(UiSourceListArgs *args, UiBool value);
+UIEXPORT void ui_sourcelist_args_set_colspan(UiSourceListArgs *args, int colspan);
+UIEXPORT void ui_sourcelist_args_set_rowspan(UiSourceListArgs *args, int rowspan);
+UIEXPORT void ui_sourcelist_args_set_name(UiSourceListArgs *args, const char *name);
+UIEXPORT void ui_sourcelist_args_set_style_class(UiSourceListArgs *args, const char *classname);
+UIEXPORT void ui_sourcelist_args_set_static_sublists(UiSourceListArgs *args, UiSubList *sublists, size_t numsublists);
+UIEXPORT void ui_sourcelist_args_set_varname(UiSourceListArgs *args, const char *varname);
+UIEXPORT void ui_sourcelist_args_set_dynamic_sublists(UiSourceListArgs *args, UiList *value);
+UIEXPORT void ui_sourcelist_args_set_getvalue_func(UiSourceListArgs *args, ui_sublist_getvalue_func getvalue);
+UIEXPORT void ui_sourcelist_args_set_getvalue_userdata(UiSourceListArgs *args, void *userdata);
+UIEXPORT void ui_sourcelist_args_set_onactivate(UiSourceListArgs *args, ui_callback callback);
+UIEXPORT void ui_sourcelist_args_set_onactivatedata(UiSourceListArgs *args, void *userdata);
+UIEXPORT void ui_sourcelist_args_set_onbuttonclick(UiSourceListArgs *args, ui_callback callback);
+UIEXPORT void ui_sourcelist_args_set_onbuttonclickdata(UiSourceListArgs *args, void *userdata);
+UIEXPORT void ui_sourcelist_args_free(UiSourceListArgs *args);
+
+UIEXPORT UiTextAreaArgs* ui_textarea_args_new(void);
+UIEXPORT void ui_textarea_args_set_fill(UiTextAreaArgs *args, UiBool fill);
+UIEXPORT void ui_textarea_args_set_hexpand(UiTextAreaArgs *args, UiBool value);
+UIEXPORT void ui_textarea_args_set_vexpand(UiTextAreaArgs *args, UiBool value);
+UIEXPORT void ui_textarea_args_set_hfill(UiTextAreaArgs *args, UiBool value);
+UIEXPORT void ui_textarea_args_set_vfill(UiTextAreaArgs *args, UiBool value);
+UIEXPORT void ui_textarea_args_set_override_defaults(UiTextAreaArgs *args, UiBool value);
+UIEXPORT void ui_textarea_args_set_colspan(UiTextAreaArgs *args, int colspan);
+UIEXPORT void ui_textarea_args_set_rowspan(UiTextAreaArgs *args, int rowspan);
+UIEXPORT void ui_textarea_args_set_name(UiTextAreaArgs *args, const char *name);
+UIEXPORT void ui_textarea_args_set_style_class(UiTextAreaArgs *args, const char *classname);
+UIEXPORT void ui_textarea_args_set_onchange(UiTextAreaArgs *args, ui_callback callback);
+UIEXPORT void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata);
+UIEXPORT void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname);
+UIEXPORT void ui_textarea_args_set_value(UiTextAreaArgs *args, UiText *value);
+UIEXPORT void ui_textarea_args_set_groups(UiTextAreaArgs *args, int *groups);
+UIEXPORT void ui_textarea_args_free(UiTextAreaArgs *args);
+
+UIEXPORT UiTextFieldArgs* ui_textfield_args_new(void);
+UIEXPORT void ui_textfield_args_set_fill(UiTextFieldArgs *args, UiBool fill);
+UIEXPORT void ui_textfield_args_set_hexpand(UiTextFieldArgs *args, UiBool value);
+UIEXPORT void ui_textfield_args_set_vexpand(UiTextFieldArgs *args, UiBool value);
+UIEXPORT void ui_textfield_args_set_hfill(UiTextFieldArgs *args, UiBool value);
+UIEXPORT void ui_textfield_args_set_vfill(UiTextFieldArgs *args, UiBool value);
+UIEXPORT void ui_textfield_args_set_override_defaults(UiTextFieldArgs *args, UiBool value);
+UIEXPORT void ui_textfield_args_set_colspan(UiTextFieldArgs *args, int colspan);
+UIEXPORT void ui_textfield_args_set_rowspan(UiTextFieldArgs *args, int rowspan);
+UIEXPORT void ui_textfield_args_set_name(UiTextFieldArgs *args, const char *name);
+UIEXPORT void ui_textfield_args_set_style_class(UiTextFieldArgs *args, const char *classname);
+UIEXPORT void ui_textfield_args_set_onchange(UiTextFieldArgs *args, ui_callback callback);
+UIEXPORT void ui_textfield_args_set_onchangedata(UiTextFieldArgs *args, void *onchangedata);
+UIEXPORT void ui_textfield_args_set_onactivate(UiTextFieldArgs *args, ui_callback callback);
+UIEXPORT void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivatedata);
+UIEXPORT void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname);
+UIEXPORT void ui_textfield_args_set_value(UiTextFieldArgs *args, UiString *value);
+UIEXPORT void ui_textfield_args_set_groups(UiTextFieldArgs *args, int *groups);
+UIEXPORT void ui_textfield_args_free(UiTextFieldArgs *args);
+
+UIEXPORT UiWebviewArgs* ui_webview_args_new(void);
+UIEXPORT void ui_webview_args_set_fill(UiWebviewArgs *args, UiBool fill);
+UIEXPORT void ui_webview_args_set_hexpand(UiWebviewArgs *args, UiBool value);
+UIEXPORT void ui_webview_args_set_vexpand(UiWebviewArgs *args, UiBool value);
+UIEXPORT void ui_webview_args_set_hfill(UiWebviewArgs *args, UiBool value);
+UIEXPORT void ui_webview_args_set_vfill(UiWebviewArgs *args, UiBool value);
+UIEXPORT void ui_webview_args_set_override_defaults(UiWebviewArgs *args, UiBool value);
+UIEXPORT void ui_webview_args_set_colspan(UiWebviewArgs *args, int colspan);
+UIEXPORT void ui_webview_args_set_rowspan(UiWebviewArgs *args, int rowspan);
+UIEXPORT void ui_webview_args_set_name(UiWebviewArgs *args, const char *name);
+UIEXPORT void ui_webview_args_set_style_class(UiWebviewArgs *args, const char *classname);
+UIEXPORT void ui_webview_args_set_varname(UiWebviewArgs *args, const char *varname);
+UIEXPORT void ui_webview_args_set_value(UiWebviewArgs *args, UiGeneric *value);
+UIEXPORT void ui_webview_args_set_groups(UiWebviewArgs *args, int *groups);
+UIEXPORT void ui_webview_args_free(UiWebviewArgs *args);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UIC_ARGS_H */
+
diff --git a/ui/common/context.c b/ui/common/context.c
index db9d850..d0cd53d 100644
--- a/ui/common/context.c
+++ b/ui/common/context.c
@@ -67,7 +67,7 @@ UiContext* uic_context(UiObject *toplevel, CxMempool *mp) {
ctx->groups = cxArrayListCreate(mp->allocator, cx_cmp_int, sizeof(int), 32);
ctx->attach_document = uic_context_attach_document;
- ctx->detach_document2 = uic_context_detach_document2;
+ ctx->detach_document2 = uic_context_detach_document;
#if UI_GTK2 || UI_GTK3
if(toplevel && toplevel->widget) {
@@ -146,7 +146,7 @@ static void uic_context_unbind_vars(UiContext *ctx) {
}
}
-void uic_context_detach_document2(UiContext *ctx, void *document) {
+void uic_context_detach_document(UiContext *ctx, void *document) {
// find the document in the documents list
size_t docIndex = cxListFind(ctx->documents, document);
if(!cxListIndexValid(ctx->documents, docIndex)) {
@@ -409,7 +409,7 @@ void uic_unbind_var(UiVar *var) {
}
}
-void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value) {
+void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value) {
// TODO: do we need/want this? Why adding vars to a context after
// widgets reference these? Workarounds:
// 1. add vars to ctx before creating ui
@@ -467,8 +467,8 @@ void ui_attach_document(UiContext *ctx, void *document) {
uic_context_attach_document(ctx, document);
}
-void ui_detach_document2(UiContext *ctx, void *document) {
- uic_context_detach_document2(ctx, document);
+void ui_detach_document(UiContext *ctx, void *document) {
+ uic_context_detach_document(ctx, document);
}
void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) {
@@ -476,7 +476,7 @@ void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) {
ctx->close_data = udata;
}
-UIEXPORT void ui_context_destroy(UiContext *ctx) {
+void ui_context_destroy(UiContext *ctx) {
CxIterator i = cxListIterator(ctx->destroy_handler);
cx_foreach(UiDestroyHandler *, h, i) {
h->destructor(h->data);
@@ -484,6 +484,10 @@ UIEXPORT void ui_context_destroy(UiContext *ctx) {
cxMempoolFree(ctx->mp);
}
+UiContext* ui_context_parent(UiContext *ctx) {
+ return ctx->parent;
+}
+
void ui_set_group(UiContext *ctx, int group) {
if(!cxListIndexValid(ctx->groups, cxListFind(ctx->groups, &group))) {
diff --git a/ui/common/context.h b/ui/common/context.h
index e0ce3de..4fdcfe6 100644
--- a/ui/common/context.h
+++ b/ui/common/context.h
@@ -119,15 +119,13 @@ void uic_init_global_context(void);
UiContext* uic_context(UiObject *toplevel, CxMempool *mp);
UiContext* uic_root_context(UiContext *ctx);
void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *data);
-void uic_context_set_document(UiContext *ctx, void *document); // deprecated
-void uic_context_detach_document(UiContext *ctx); // deprecated
void uic_context_prepare_close(UiContext *ctx);
void uic_context_attach_document(UiContext *ctx, void *document);
-void uic_context_detach_document2(UiContext *ctx, void *document);
-void uic_context_attach_context(UiContext *ctx, UiContext *doc_ctx);
-void uic_context_detach_context(UiContext *ctx, UiContext *doc_ctx);
+void uic_context_detach_document(UiContext *ctx, void *document);
+void uic_context_attach_context(UiContext *ctx, UiContext *doc_ctx); // TODO
+void uic_context_detach_context(UiContext *ctx, UiContext *doc_ctx); // TODO
void uic_context_detach_all(UiContext *ctx);
UiVar* uic_get_var(UiContext *ctx, const char *name);
@@ -141,7 +139,7 @@ void uic_copy_binding(UiVar *from, UiVar *to, UiBool copytodoc);
void uic_save_var2(UiVar *var);
void uic_unbind_var(UiVar *var);
-void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value);
+void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value);
void uic_remove_bound_var(UiContext *ctx, UiVar *var);
diff --git a/ui/common/document.c b/ui/common/document.c
index 07177bd..bd69073 100644
--- a/ui/common/document.c
+++ b/ui/common/document.c
@@ -44,44 +44,6 @@ void uic_docmgr_init() {
}
}
-void ui_set_document(UiObject *obj, void *document) {
- uic_context_detach_all(obj->ctx);
- obj->ctx->attach_document(obj->ctx, document);
-}
-
-void ui_detach_document(UiObject *obj) {
- uic_context_detach_all(obj->ctx);
-}
-
-void* ui_get_document(UiObject *obj) {
- return obj->ctx->document;
-}
-
-void ui_set_subdocument(void *document, void *sub) {
- UiContext *ctx = ui_document_context(document);
- if(!ctx) {
- fprintf(stderr, "UI Error: pointer is not a document\n");
- }
- // TODO
-}
-
-void ui_detach_subdocument(void *document, void *sub) {
- UiContext *ctx = ui_document_context(document);
- if(!ctx) {
- fprintf(stderr, "UI Error: pointer is not a document\n");
- }
- // TODO
-}
-
-void* ui_get_subdocument(void *document) {
- UiContext *ctx = ui_document_context(document);
- if(!ctx) {
- fprintf(stderr, "UI Error: pointer is not a document\n");
- }
- // TODO
- return NULL;
-}
-
void* ui_document_new(size_t size) {
CxMempool *mp = cxMempoolCreateSimple(256);
const CxAllocator *a = mp->allocator;
@@ -100,6 +62,7 @@ void ui_document_destroy(void *doc) {
ev.document = doc;
ev.obj = NULL;
ev.eventdata = NULL;
+ ev.eventdatatype = 0;
ev.intval = 0;
if(ctx->close_callback) {
diff --git a/ui/common/menu.c b/ui/common/menu.c
index 4b23418..31f8171 100644
--- a/ui/common/menu.c
+++ b/ui/common/menu.c
@@ -125,19 +125,19 @@ UIEXPORT void ui_menu_end(void) {
-void ui_menuitem_create(UiMenuItemArgs args) {
+void ui_menuitem_create(UiMenuItemArgs *args) {
UiMenuItem* item = malloc(sizeof(UiMenuItem));
mitem_set_id(&item->item);
item->item.prev = NULL;
item->item.next = NULL;
item->item.type = UI_MENU_ITEM;
- item->label = nl_strdup(args.label);
- item->stockid = nl_strdup(args.stockid);
- item->icon = nl_strdup(args.icon);
- item->userdata = args.onclickdata;
- item->callback = args.onclick;
- item->groups = uic_copy_groups(args.groups, &item->ngroups);
+ item->label = nl_strdup(args->label);
+ item->stockid = nl_strdup(args->stockid);
+ item->icon = nl_strdup(args->icon);
+ item->userdata = args->onclickdata;
+ item->callback = args->onclick;
+ item->groups = uic_copy_groups(args->groups, &item->ngroups);
add_item((UiMenuItemI*)item);
}
@@ -152,79 +152,79 @@ void ui_menuseparator() {
add_item((UiMenuItemI*)item);
}
-void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) {
+void ui_menu_toggleitem_create(UiMenuToggleItemArgs *args) {
UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem));
mitem_set_id(&item->item);
item->item.prev = NULL;
item->item.next = NULL;
item->item.type = UI_MENU_CHECK_ITEM;
- item->label = nl_strdup(args.label);
- item->stockid = nl_strdup(args.stockid);
- item->icon = nl_strdup(args.icon);
- item->varname = nl_strdup(args.varname);
- item->userdata = args.onchangedata;
- item->callback = args.onchange;
- item->groups = uic_copy_groups(args.groups, &item->ngroups);
+ item->label = nl_strdup(args->label);
+ item->stockid = nl_strdup(args->stockid);
+ item->icon = nl_strdup(args->icon);
+ item->varname = nl_strdup(args->varname);
+ item->userdata = args->onchangedata;
+ item->callback = args->onchange;
+ item->groups = uic_copy_groups(args->groups, &item->ngroups);
add_item((UiMenuItemI*)item);
}
-void ui_menu_radioitem_create(UiMenuToggleItemArgs args) {
+void ui_menu_radioitem_create(UiMenuToggleItemArgs *args) {
UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem));
mitem_set_id(&item->item);
item->item.prev = NULL;
item->item.next = NULL;
item->item.type = UI_MENU_RADIO_ITEM;
- item->label = nl_strdup(args.label);
- item->stockid = nl_strdup(args.stockid);
- item->icon = nl_strdup(args.icon);
- item->varname = nl_strdup(args.varname);
- item->userdata = args.onchangedata;
- item->callback = args.onchange;
- item->groups = uic_copy_groups(args.groups, &item->ngroups);
+ item->label = nl_strdup(args->label);
+ item->stockid = nl_strdup(args->stockid);
+ item->icon = nl_strdup(args->icon);
+ item->varname = nl_strdup(args->varname);
+ item->userdata = args->onchangedata;
+ item->callback = args->onchange;
+ item->groups = uic_copy_groups(args->groups, &item->ngroups);
add_item((UiMenuItemI*)item);
}
-void ui_menu_itemlist_create(UiMenuItemListArgs args) {
+void ui_menu_itemlist_create(UiMenuItemListArgs *args) {
UiMenuItemList*item = malloc(sizeof(UiMenuItemList));
mitem_set_id(&item->item);
item->item.prev = NULL;
item->item.next = NULL;
item->item.type = UI_MENU_ITEM_LIST;
- item->getvalue = args.getvalue;
- item->callback = args.onselect;
- item->userdata = args.onselectdata;
- item->varname = nl_strdup(args.varname);
- item->addseparator = args.addseparator;
+ item->getvalue = args->getvalue;
+ item->callback = args->onselect;
+ item->userdata = args->onselectdata;
+ item->varname = nl_strdup(args->varname);
+ item->addseparator = args->addseparator;
add_item((UiMenuItemI*)item);
}
-void ui_menu_checkitemlist_create(UiMenuItemListArgs args) {
+void ui_menu_checkitemlist_create(UiMenuItemListArgs *args) {
UiMenuItemList* item = malloc(sizeof(UiMenuItemList));
mitem_set_id(&item->item);
item->item.prev = NULL;
item->item.next = NULL;
item->item.type = UI_MENU_CHECKITEM_LIST;
- item->callback = args.onselect;
- item->userdata = args.onselectdata;
- item->varname = nl_strdup(args.varname);
+ item->callback = args->onselect;
+ item->userdata = args->onselectdata;
+ item->varname = nl_strdup(args->varname);
add_item((UiMenuItemI*)item);
}
-void ui_menu_radioitemlist_create(UiMenuItemListArgs args) {
+void ui_menu_radioitemlist_create(UiMenuItemListArgs *args) {
UiMenuItemList* item = malloc(sizeof(UiMenuItemList));
mitem_set_id(&item->item);
item->item.prev = NULL;
item->item.next = NULL;
item->item.type = UI_MENU_RADIOITEM_LIST;
- item->callback = args.onselect;
- item->userdata = args.onselectdata;
- item->varname = nl_strdup(args.varname);
+ item->callback = args->onselect;
+ item->userdata = args->onselectdata;
+ item->varname = nl_strdup(args->varname);
add_item((UiMenuItemI*)item);
}
diff --git a/ui/common/object.c b/ui/common/object.c
index 2c10597..e7981c4 100644
--- a/ui/common/object.c
+++ b/ui/common/object.c
@@ -32,8 +32,48 @@
#include "object.h"
#include "context.h"
+#include
+
#include "../ui/container.h"
+static CxList *creation_callbacks;
+static CxList *destruction_callbacks;
+
+typedef struct objcallback {
+ ui_object_callback func;
+ void *userdata;
+} objcallback;
+
+void ui_register_object_creation_callback(ui_object_callback func, void *userdata) {
+ if(!creation_callbacks) {
+ creation_callbacks = cxLinkedListCreateSimple(sizeof(objcallback));
+ }
+ objcallback cb = { func, userdata };
+ cxListAdd(creation_callbacks, &cb);
+}
+
+void ui_register_object_destruction_callback(ui_object_callback func, void *userdata) {
+ if(!destruction_callbacks) {
+ destruction_callbacks = cxLinkedListCreateSimple(sizeof(objcallback));
+ }
+ objcallback cb = { func, userdata };
+ cxListAdd(destruction_callbacks, &cb);
+}
+
+void uic_object_created(UiObject *obj) {
+ CxIterator i = cxListIterator(creation_callbacks);
+ cx_foreach(objcallback *, cb, i) {
+ cb->func(obj, cb->userdata);
+ }
+}
+
+void uic_object_destroyed(UiObject *obj) {
+ CxIterator i = cxListIterator(destruction_callbacks);
+ cx_foreach(objcallback *, cb, i) {
+ cb->func(obj, cb->userdata);
+ }
+}
+
void ui_end(UiObject *obj) {
if(!obj->next) {
return;
@@ -84,12 +124,22 @@ void uic_object_destroy(UiObject *obj) {
ev.document = obj->ctx->document;
ev.obj = obj;
ev.eventdata = NULL;
+ ev.eventdatatype = 0;
ev.intval = 0;
obj->ctx->close_callback(&ev, obj->ctx->close_data);
}
+ uic_object_destroyed(obj);
cxMempoolFree(obj->ctx->mp);
}
+UiObject* uic_object_new_toplevel(void) {
+ CxMempool *mp = cxMempoolCreateSimple(256);
+ UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject));
+ obj->ctx = uic_context(obj, mp);
+ uic_object_created(obj);
+ return obj;
+}
+
UiObject* uic_object_new(UiObject *toplevel, UIWIDGET widget) {
return uic_ctx_object_new(toplevel->ctx, widget);
}
@@ -98,7 +148,7 @@ UiObject* uic_ctx_object_new(UiContext *ctx, UIWIDGET widget) {
UiObject *newobj = cxCalloc(ctx->allocator, 1, sizeof(UiObject));
newobj->ctx = ctx;
newobj->widget = widget;
-
+ uic_object_created(newobj);
return newobj;
}
diff --git a/ui/common/object.h b/ui/common/object.h
index a5011a0..45cf683 100644
--- a/ui/common/object.h
+++ b/ui/common/object.h
@@ -35,8 +35,17 @@
extern "C" {
#endif
+typedef void (*ui_object_callback)(UiObject *obj, void *userdata);
+
+void ui_register_object_creation_callback(ui_object_callback func, void *userdata);
+void ui_register_object_destruction_callback(ui_object_callback func, void *userdata);
+
+void uic_object_created(UiObject *obj);
+void uic_object_destroyed(UiObject *obj);
+
void uic_object_destroy(UiObject *obj);
+UiObject* uic_object_new_toplevel(void);
UiObject* uic_object_new(UiObject *toplevel, UIWIDGET widget);
UiObject* uic_ctx_object_new(UiContext *ctx, UIWIDGET widget);
void uic_obj_add(UiObject *toplevel, UiObject *ctobj);
diff --git a/ui/common/objs.mk b/ui/common/objs.mk
index bc1b385..a126b56 100644
--- a/ui/common/objs.mk
+++ b/ui/common/objs.mk
@@ -33,13 +33,14 @@ COMMON_OBJ = context$(OBJ_EXT)
COMMON_OBJ += document$(OBJ_EXT)
COMMON_OBJ += object$(OBJ_EXT)
COMMON_OBJ += types$(OBJ_EXT)
-COMMON_OBJ += menu$(OBJ_EXT)
COMMON_OBJ += properties$(OBJ_EXT)
COMMON_OBJ += menu$(OBJ_EXT)
COMMON_OBJ += toolbar$(OBJ_EXT)
COMMON_OBJ += ucx_properties$(OBJ_EXT)
COMMON_OBJ += threadpool$(OBJ_EXT)
COMMON_OBJ += condvar$(OBJ_EXT)
+COMMON_OBJ += args$(OBJ_EXT)
+COMMON_OBJ += wrapper$(OBJ_EXT)
TOOLKITOBJS += $(COMMON_OBJ:%=$(COMMON_OBJPRE)uic_%)
TOOLKITSOURCE += $(COMMON_OBJ:%$(OBJ_EXT)=common/%.c)
diff --git a/ui/common/threadpool.c b/ui/common/threadpool.c
index 7a37407..7988eab 100644
--- a/ui/common/threadpool.c
+++ b/ui/common/threadpool.c
@@ -165,6 +165,7 @@ static int ui_threadpool_job_finish(void *data) {
event.document = job->obj->ctx->document;
event.intval = 0;
event.eventdata = NULL;
+ event.eventdatatype = 0;
job->finish_callback(&event, job->finish_data);
free(job);
return 0;
diff --git a/ui/common/toolbar.c b/ui/common/toolbar.c
index 0d86f17..199dc41 100644
--- a/ui/common/toolbar.c
+++ b/ui/common/toolbar.c
@@ -49,18 +49,18 @@ static char* nl_strdup(const char* str) {
return str ? strdup(str) : NULL;
}
-static UiToolbarItemArgs itemargs_copy(UiToolbarItemArgs args, size_t *ngroups) {
+static UiToolbarItemArgs itemargs_copy(UiToolbarItemArgs *args, size_t *ngroups) {
UiToolbarItemArgs newargs;
- newargs.label = nl_strdup(args.label);
- newargs.stockid = nl_strdup(args.stockid);
- newargs.icon = nl_strdup(args.icon);
- newargs.onclick = args.onclick;
- newargs.onclickdata = args.onclickdata;
- newargs.groups = uic_copy_groups(args.groups, ngroups);
+ newargs.label = nl_strdup(args->label);
+ newargs.stockid = nl_strdup(args->stockid);
+ newargs.icon = nl_strdup(args->icon);
+ newargs.onclick = args->onclick;
+ newargs.onclickdata = args->onclickdata;
+ newargs.groups = uic_copy_groups(args->groups, ngroups);
return newargs;
}
-void ui_toolbar_item_create(const char* name, UiToolbarItemArgs args) {
+void ui_toolbar_item_create(const char* name, UiToolbarItemArgs *args) {
UiToolbarItem* item = malloc(sizeof(UiToolbarItem));
item->item.type = UI_TOOLBAR_ITEM;
item->args = itemargs_copy(args, &item->ngroups);
@@ -68,34 +68,34 @@ void ui_toolbar_item_create(const char* name, UiToolbarItemArgs args) {
}
-static UiToolbarToggleItemArgs toggleitemargs_copy(UiToolbarToggleItemArgs args, size_t *ngroups) {
+static UiToolbarToggleItemArgs toggleitemargs_copy(UiToolbarToggleItemArgs *args, size_t *ngroups) {
UiToolbarToggleItemArgs newargs;
- newargs.label = nl_strdup(args.label);
- newargs.stockid = nl_strdup(args.stockid);
- newargs.icon = nl_strdup(args.icon);
- newargs.varname = nl_strdup(args.varname);
- newargs.onchange = args.onchange;
- newargs.onchangedata = args.onchangedata;
- newargs.groups = uic_copy_groups(args.groups, ngroups);
+ newargs.label = nl_strdup(args->label);
+ newargs.stockid = nl_strdup(args->stockid);
+ newargs.icon = nl_strdup(args->icon);
+ newargs.varname = nl_strdup(args->varname);
+ newargs.onchange = args->onchange;
+ newargs.onchangedata = args->onchangedata;
+ newargs.groups = uic_copy_groups(args->groups, ngroups);
return newargs;
}
-void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs args) {
+void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs *args) {
UiToolbarToggleItem* item = malloc(sizeof(UiToolbarToggleItem));
item->item.type = UI_TOOLBAR_TOGGLEITEM;
item->args = toggleitemargs_copy(args, &item->ngroups);
cxMapPut(toolbar_items, name, item);
}
-static UiToolbarMenuArgs menuargs_copy(UiToolbarMenuArgs args) {
+static UiToolbarMenuArgs menuargs_copy(UiToolbarMenuArgs *args) {
UiToolbarMenuArgs newargs;
- newargs.label = nl_strdup(args.label);
- newargs.stockid = nl_strdup(args.stockid);
- newargs.icon = nl_strdup(args.icon);
+ newargs.label = nl_strdup(args->label);
+ newargs.stockid = nl_strdup(args->stockid);
+ newargs.icon = nl_strdup(args->icon);
return newargs;
}
-UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs args) {
+UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs *args) {
UiToolbarMenuItem* item = malloc(sizeof(UiToolbarMenuItem));
item->item.type = UI_TOOLBAR_MENU;
memset(&item->menu, 0, sizeof(UiMenu));
diff --git a/ui/common/types.c b/ui/common/types.c
index a704b85..b3f55d1 100644
--- a/ui/common/types.c
+++ b/ui/common/types.c
@@ -36,8 +36,10 @@
#include "../ui/tree.h"
#include "types.h"
#include "context.h"
+#include "../ui/image.h"
-
+static ui_list_init_func default_list_init;
+static void *default_list_init_userdata;
UiObserver* ui_observer_new(ui_callback f, void *data) {
UiObserver *observer = malloc(sizeof(UiObserver));
@@ -75,6 +77,7 @@ void ui_notify_except(UiObserver *observer, UiObserver *exc, void *data) {
evt.window = NULL;
evt.document = NULL;
evt.eventdata = data;
+ evt.eventdatatype = UI_EVENT_DATA_POINTER;
evt.intval = 0;
while(observer) {
@@ -94,20 +97,22 @@ void ui_notify_evt(UiObserver *observer, UiEvent *event) {
/* --------------------------- UiList --------------------------- */
-UiList* ui_list_new(UiContext *ctx, char *name) {
- UiList *list = malloc(sizeof(UiList));
+void uic_ucx_list_init(UiContext *ctx, UiList *list, void *unused) {
+ list->data = cxArrayListCreate(ctx->mp->allocator, NULL, CX_STORE_POINTERS, 32);
list->first = ui_list_first;
list->next = ui_list_next;
list->get = ui_list_get;
list->count = ui_list_count;
- list->observers = NULL;
-
- list->data = cxArrayListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS, 32);
- list->iter = NULL;
-
- list->update = NULL;
- list->getselection = NULL;
- list->obj = NULL;
+}
+
+UiList* ui_list_new(UiContext *ctx, const char *name) {
+ return ui_list_new2(ctx, name, default_list_init ? default_list_init : uic_ucx_list_init, default_list_init_userdata);
+}
+
+UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func listinit, void *userdata) {
+ UiList *list = cxMalloc(ctx->mp->allocator, sizeof(UiList));
+ memset(list, 0, sizeof(UiList));
+ listinit(ctx, list, userdata);
if(name) {
uic_reg_var(ctx, name, UI_VAR_LIST, list);
@@ -248,7 +253,7 @@ void ui_model_free(UiContext *ctx, UiModel *mi) {
// types
// public functions
-UiInteger* ui_int_new(UiContext *ctx, char *name) {
+UiInteger* ui_int_new(UiContext *ctx, const char *name) {
UiInteger *i = ui_malloc(ctx, sizeof(UiInteger));
memset(i, 0, sizeof(UiInteger));
if(name) {
@@ -257,7 +262,7 @@ UiInteger* ui_int_new(UiContext *ctx, char *name) {
return i;
}
-UiDouble* ui_double_new(UiContext *ctx, char *name) {
+UiDouble* ui_double_new(UiContext *ctx, const char *name) {
UiDouble *d = ui_malloc(ctx, sizeof(UiDouble));
memset(d, 0, sizeof(UiDouble));
if(name) {
@@ -266,7 +271,7 @@ UiDouble* ui_double_new(UiContext *ctx, char *name) {
return d;
}
-UiString* ui_string_new(UiContext *ctx, char *name) {
+UiString* ui_string_new(UiContext *ctx, const char *name) {
UiString *s = ui_malloc(ctx, sizeof(UiString));
memset(s, 0, sizeof(UiString));
if(name) {
@@ -275,7 +280,7 @@ UiString* ui_string_new(UiContext *ctx, char *name) {
return s;
}
-UiText* ui_text_new(UiContext *ctx, char *name) {
+UiText* ui_text_new(UiContext *ctx, const char *name) {
UiText *t = ui_malloc(ctx, sizeof(UiText));
memset(t, 0, sizeof(UiText));
if(name) {
@@ -284,7 +289,7 @@ UiText* ui_text_new(UiContext *ctx, char *name) {
return t;
}
-UiRange* ui_range_new(UiContext *ctx, char *name) {
+UiRange* ui_range_new(UiContext *ctx, const char *name) {
UiRange *r = ui_malloc(ctx, sizeof(UiRange));
memset(r, 0, sizeof(UiRange));
if(name) {
@@ -293,7 +298,7 @@ UiRange* ui_range_new(UiContext *ctx, char *name) {
return r;
}
-UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, char *name) {
+UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, const char *name) {
UiGeneric *g = ui_malloc(ctx, sizeof(UiGeneric));
memset(g, 0, sizeof(UiGeneric));
if(name) {
@@ -404,6 +409,30 @@ char* ui_text_get(UiText* s) {
}
}
+void ui_generic_set_image(UiGeneric *g, void *img) {
+ if(g->set) {
+ g->set(g, img, UI_IMAGE_OBJECT_TYPE);
+ } else {
+ if(g->value) {
+ ui_image_unref(g->value);
+ }
+ ui_image_ref(img);
+ g->value = img;
+ g->type = UI_IMAGE_OBJECT_TYPE;
+ }
+}
+
+void* ui_generic_get_image(UiGeneric *g) {
+ if(g->type) {
+ if(!strcmp(g->type, UI_IMAGE_OBJECT_TYPE)) {
+ return g->value;
+ } else {
+ return NULL;
+ }
+ }
+ return g->value;
+}
+
// private functions
void uic_int_copy(UiInteger *from, UiInteger *to) {
@@ -636,3 +665,34 @@ void ui_setop_enable(int set) {
int ui_get_setop(void) {
return ui_set_op;
}
+
+/* ---------------- List initializers and wrapper functions ---------------- */
+
+void ui_global_list_initializer(ui_list_init_func func, void *userdata) {
+ default_list_init = func;
+ default_list_init_userdata = userdata;
+}
+
+void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list)) {
+ list->first = first;
+}
+
+void ui_list_class_set_next(UiList *list, void*(*next)(UiList *list)) {
+ list->next = next;
+}
+
+void ui_list_class_set_get(UiList *list, void*(*get)(UiList *list, int i)) {
+ list->get = get;
+}
+
+void ui_list_class_set_count(UiList *list, int(*count)(UiList *list)) {
+ list->count = count;
+}
+
+void ui_list_class_set_data(UiList *list, void *data) {
+ list->data = data;
+}
+
+void ui_list_class_set_iter(UiList *list, void *iter) {
+ list->iter = iter;
+}
diff --git a/ui/common/types.h b/ui/common/types.h
index 677199f..46d6c2e 100644
--- a/ui/common/types.h
+++ b/ui/common/types.h
@@ -34,8 +34,9 @@
#ifdef __cplusplus
extern "C" {
#endif
-
-
+
+void uic_ucx_list_init(UiContext *ctx, UiList *list, void *unused);
+
void uic_int_copy(UiInteger *from, UiInteger *to);
void uic_double_copy(UiDouble *from, UiDouble *to);
void uic_string_copy(UiString *from, UiString *to);
diff --git a/ui/common/wrapper.c b/ui/common/wrapper.c
new file mode 100644
index 0000000..ea88553
--- /dev/null
+++ b/ui/common/wrapper.c
@@ -0,0 +1,220 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 "wrapper.h"
+#include "types.h"
+#include
+#include
+
+/* ---------------------------- UiObject ---------------------------- */
+
+UiContext* ui_object_get_context(UiObject *obj) {
+ return obj->ctx;
+}
+
+void* ui_object_get_windowdata(UiObject *obj) {
+ return obj->window;
+}
+
+void ui_object_set_windowdata(UiObject *obj, void *windowdata) {
+ obj->window = windowdata;
+}
+
+
+/* ---------------------------- UiList ---------------------------- */
+
+void* ui_list_get_data(UiList *list) {
+ return list->data;
+}
+
+void ui_list_set_data(UiList *list, void *data) {
+ list->data = data;
+}
+
+void* ui_list_get_iter(UiList *list) {
+ return list->iter;
+}
+
+void ui_list_set_iter(UiList *list, void *iter) {
+ list->iter = iter;
+}
+
+
+/* ------------------------------ UiSublist ------------------------------ */
+
+UiSubList* ui_sublist_new(void) {
+ UiSubList *sublist = malloc(sizeof(UiSubList));
+ memset(sublist, 0, sizeof(UiSubList));
+ return sublist;
+}
+
+void ui_sublist_set_value(UiSubList *sublist, UiList *value) {
+ sublist->value = value;
+}
+
+void ui_sublist_set_varname(UiSubList *sublist, const char *varname) {
+ free((void*)sublist->varname);
+ sublist->varname = strdup(varname);
+}
+
+void ui_sublist_set_header(UiSubList *sublist, const char *header) {
+ free((void*)sublist->header);
+ sublist->header = strdup(header);
+}
+
+void ui_sublist_set_separator(UiSubList *sublist, UiBool separator) {
+ sublist->separator = separator;
+}
+
+void ui_sublist_set_userdata(UiSubList *sublist, void *userdata) {
+ sublist->userdata = userdata;
+}
+
+void ui_sublist_free(UiSubList *sublist) {
+ free((void*)sublist->varname);
+ free((void*)sublist->header);
+ free(sublist);
+}
+
+
+/* -------------------- Source list (UiList) -------------------- */
+
+UiList* ui_srclist_new(UiContext *ctx, const char *name) {
+ UiList *list = ui_list_new2(ctx, name, uic_ucx_list_init, NULL);
+ CxList *cxlist = list->data;
+ cxlist->collection.simple_destructor = (cx_destructor_func)ui_sublist_free;
+ return list;
+}
+
+void ui_srclist_add(UiList *list, UiSubList *item) {
+ ui_list_append(list, item);
+}
+
+void ui_srclist_insert(UiList *list, int index, UiSubList *item) {
+ CxList *cxlist = list->data;
+ cxListInsert(cxlist, index, item);
+}
+
+void ui_srclist_remove(UiList *list, int index) {
+ CxList *cxlist = list->data;
+ cxListRemove(cxlist, index);
+}
+
+void ui_srclist_clear(UiList *list) {
+ CxList *cxlist = list->data;
+ cxListClear(cxlist);
+}
+
+int ui_srclist_size(UiList *list) {
+ return ui_list_count(list);
+}
+
+
+/* ---------------------------- UiSubListEventData ---------------------------- */
+
+UiList* ui_sublist_event_get_list(UiSubListEventData *event) {
+ return event->list;
+}
+
+int ui_sublist_event_get_sublist_index(UiSubListEventData *event) {
+ return event->sublist_index;
+}
+
+int ui_sublist_event_get_row_index(UiSubListEventData *event) {
+ return event->row_index;
+}
+
+void* ui_sublist_event_get_row_data(UiSubListEventData *event) {
+ return event->row_data;
+}
+
+void* ui_sublist_event_get_sublist_userdata(UiSubListEventData *event) {
+ return event->sublist_userdata;
+}
+
+void* ui_sublist_event_get_event_data(UiSubListEventData *event) {
+ return event->event_data;
+}
+
+
+/* ---------------------------- UiEvent ---------------------------- */
+
+UiObject* ui_event_get_obj(UiEvent *event) {
+ return event->obj;
+}
+
+void* ui_event_get_document(UiEvent *event) {
+ return event->document;
+}
+
+void* ui_event_get_windowdata(UiEvent *event) {
+ return event->window;
+}
+
+void* ui_event_get_eventdata(UiEvent *event) {
+ return event->eventdata;
+}
+
+int ui_event_get_eventdatatype(UiEvent *event) {
+ return event->eventdatatype;
+}
+
+int ui_event_get_int(UiEvent *event) {
+ return event->intval;
+}
+
+int ui_event_get_set(UiEvent *event) {
+ return event->set;
+}
+
+
+/* ------------------------- SubListItem (public) ------------------------- */
+
+void ui_sublist_item_set_icon(UiSubListItem *item, const char *icon) {
+ item->icon = icon ? strdup(icon) : NULL;
+}
+
+void ui_sublist_item_set_label(UiSubListItem *item, const char *label) {
+ item->label = label ? strdup(label) : NULL;
+}
+
+void ui_sublist_item_set_button_icon(UiSubListItem *item, const char *button_icon) {
+ item->button_icon = button_icon ? strdup(button_icon) : NULL;
+}
+
+void ui_sublist_item_set_button_label(UiSubListItem *item, const char *button_label) {
+ item->button_label = button_label ? strdup(button_label) : NULL;
+}
+
+void ui_sublist_item_set_badge(UiSubListItem *item, const char *badge) {
+ item->badge = badge ? strdup(badge) : NULL;
+}
+
+void ui_sublist_item_set_eventdata(UiSubListItem *item, void *eventdata) {
+ item->eventdata = NULL;
+}
diff --git a/ui/common/wrapper.h b/ui/common/wrapper.h
new file mode 100644
index 0000000..d190fc8
--- /dev/null
+++ b/ui/common/wrapper.h
@@ -0,0 +1,84 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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.
+ */
+
+#ifndef UIC_WRAPPER_H
+#define UIC_WRAPPER_H
+
+#include "../ui/toolkit.h"
+#include "../ui/tree.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UIEXPORT UiContext* ui_object_get_context(UiObject *obj);
+UIEXPORT void* ui_object_get_windowdata(UiObject *obj);
+UIEXPORT void ui_object_set_windowdata(UiObject *obj, void *windowdata);
+
+UIEXPORT void* ui_list_get_data(UiList *list);
+UIEXPORT void* ui_list_get_iter(UiList *list);
+UIEXPORT void ui_list_set_iter(UiList *list, void *iter);
+
+UIEXPORT UiSubList* ui_sublist_new(void);
+UIEXPORT void ui_sublist_set_value(UiSubList *sublist, UiList *value);
+UIEXPORT void ui_sublist_set_varname(UiSubList *sublist, const char *varname);
+UIEXPORT void ui_sublist_set_header(UiSubList *sublist, const char *header);
+UIEXPORT void ui_sublist_set_separator(UiSubList *sublist, UiBool separator);
+UIEXPORT void ui_sublist_set_userdata(UiSubList *sublist, void *userdata);
+UIEXPORT void ui_sublist_free(UiSubList *sublist);
+
+UIEXPORT UiList* ui_srclist_new(UiContext *ctx, const char *name);
+UIEXPORT void ui_srclist_add(UiList *list, UiSubList *item);
+UIEXPORT void ui_srclist_insert(UiList *list, int index, UiSubList *item);
+UIEXPORT void ui_srclist_remove(UiList *list, int index);
+UIEXPORT void ui_srclist_clear(UiList *list);
+UIEXPORT int ui_srclist_size(UiList *list);
+
+UIEXPORT UiList* ui_sublist_event_get_list(UiSubListEventData *event);
+UIEXPORT int ui_sublist_event_get_sublist_index(UiSubListEventData *event);
+UIEXPORT int ui_sublist_event_get_row_index(UiSubListEventData *event);
+UIEXPORT void* ui_sublist_event_get_row_data(UiSubListEventData *event);
+UIEXPORT void* ui_sublist_event_get_sublist_userdata(UiSubListEventData *event);
+UIEXPORT void* ui_sublist_event_get_event_data(UiSubListEventData *event);
+
+UIEXPORT UiObject* ui_event_get_obj(UiEvent *event);
+UIEXPORT void* ui_event_get_document(UiEvent *event);
+UIEXPORT void* ui_event_get_windowdata(UiEvent *event);
+UIEXPORT void* ui_event_get_eventdata(UiEvent *event);
+UIEXPORT int ui_event_get_eventdatatype(UiEvent *event);
+UIEXPORT int ui_event_get_int(UiEvent *event);
+UIEXPORT int ui_event_get_set(UiEvent *event);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UIC_WRAPPER_H */
+
diff --git a/ui/gtk/Makefile b/ui/gtk/Makefile
index aba263f..d1979fb 100644
--- a/ui/gtk/Makefile
+++ b/ui/gtk/Makefile
@@ -27,8 +27,10 @@
#
$(GTK_OBJPRE)%.o: gtk/%.c
- $(CC) -o $@ -c -I../ucx $(CFLAGS) $(TK_CFLAGS) $<
+ $(CC) -o $@ -c -I../ucx $(CFLAGS) $(SHLIB_CFLAGS) $(TK_CFLAGS) $<
$(UI_LIB): $(OBJ)
$(AR) $(ARFLAGS) $(UI_LIB) $(OBJ)
-
+
+$(UI_SHLIB): $(OBJ)
+ $(CC) -o $(UI_SHLIB) $(LDFLAGS) $(SHLIB_LDFLAGS) $(TK_LDFLAGS) $(OBJ) -L../build/lib -lucx
diff --git a/ui/gtk/button.c b/ui/gtk/button.c
index b26a130..6f6ad0b 100644
--- a/ui/gtk/button.c
+++ b/ui/gtk/button.c
@@ -73,6 +73,7 @@ GtkWidget* ui_create_button(
event->callback = onclick;
event->value = event_value;
event->customdata = NULL;
+ event->customint = 0;
g_signal_connect(
button,
@@ -96,13 +97,13 @@ GtkWidget* ui_create_button(
return button;
}
-UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs args) {
+UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs *args) {
UiObject* current = uic_current_obj(obj);
- GtkWidget *button = ui_create_button(obj, args.label, args.icon, args.onclick, args.onclickdata, 0, FALSE);
- ui_set_name_and_style(button, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, button, args.groups);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, button, FALSE);
+ GtkWidget *button = ui_create_button(obj, args->label, args->icon, args->onclick, args->onclickdata, 0, FALSE);
+ ui_set_name_and_style(button, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, button, args->groups);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, button);
return button;
}
@@ -113,6 +114,7 @@ void ui_button_clicked(GtkWidget *widget, UiEventData *event) {
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = event->value;
e.set = ui_get_setop();
event->callback(&e, event->userdata);
@@ -137,6 +139,7 @@ void ui_toggled_obs(void *widget, UiVarEventData *event) {
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = event->var->value;
+ e.eventdatatype = UI_EVENT_DATA_INTEGER_VALUE;
e.intval = i->get(i);
e.set = ui_get_setop();
@@ -149,6 +152,7 @@ static void ui_toggled_callback(GtkToggleButton *widget, UiEventData *event) {
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = gtk_toggle_button_get_active(widget);
e.set = ui_get_setop();
event->callback(&e, event->userdata);
@@ -240,6 +244,7 @@ void ui_bind_togglebutton(
event->callback = onchange;
event->value = 0;
event->customdata = NULL;
+ event->customint = 0;
g_signal_connect(
widget,
@@ -260,6 +265,7 @@ void ui_bind_togglebutton(
event->callback = NULL;
event->value = enable_state;
event->customdata = NULL;
+ event->customint = 0;
g_signal_connect(
widget,
@@ -274,29 +280,29 @@ void ui_bind_togglebutton(
}
}
-static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs args) {
+static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs *args) {
UiObject* current = uic_current_obj(obj);
ui_setup_togglebutton(
obj,
widget,
- args.label,
- args.icon,
- args.varname,
- args.value,
- args.onchange,
- args.onchangedata,
- args.enable_group);
- ui_set_name_and_style(widget, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, widget, args.groups);
+ args->label,
+ args->icon,
+ args->varname,
+ args->value,
+ args->onchange,
+ args->onchangedata,
+ args->enable_group);
+ ui_set_name_and_style(widget, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, widget, args->groups);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, widget, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, widget);
return widget;
}
-UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) {
+UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args) {
return togglebutton_create(obj, gtk_toggle_button_new(), args);
}
@@ -320,6 +326,7 @@ static void ui_checkbox_callback(GtkCheckButton *widget, UiEventData *event) {
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = gtk_check_button_get_active(widget);
e.set = ui_get_setop();
event->callback(&e, event->userdata);
@@ -333,39 +340,39 @@ static void ui_checkbox_enable_state(GtkCheckButton *widget, UiEventData *event)
}
}
-UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) {
+UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) {
UiObject* current = uic_current_obj(obj);
- GtkWidget *widget = gtk_check_button_new_with_label(args.label);
+ GtkWidget *widget = gtk_check_button_new_with_label(args->label);
ui_bind_togglebutton(
obj,
widget,
ui_check_button_get,
ui_check_button_set,
- args.varname,
- args.value,
+ args->varname,
+ args->value,
(ui_toggled_func)ui_checkbox_callback,
- args.onchange,
- args.onchangedata,
+ args->onchange,
+ args->onchangedata,
(ui_toggled_func)ui_checkbox_enable_state,
- args.enable_group);
+ args->enable_group);
- ui_set_name_and_style(widget, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, widget, args.groups);
+ ui_set_name_and_style(widget, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, widget, args->groups);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, widget, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, widget);
return widget;
}
#else
-UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) {
+UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) {
return togglebutton_create(obj, gtk_check_button_new(), args);
}
#endif
-UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) {
+UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) {
#ifdef UI_GTK3
return NULL; // TODO
#else
@@ -391,6 +398,7 @@ static void radiobutton_toggled(void *widget, UiEventData *event) {
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = RADIOBUTTON_GET_ACTIVE(widget);
e.set = ui_get_setop();
event->callback(&e, event->userdata);
@@ -415,13 +423,13 @@ static void destroy_radiobutton(GtkWidget *w, UiRadioButtonData *data) {
free(data);
}
-UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) {
+UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs *args) {
UiObject* current = uic_current_obj(obj);
GSList *rg = NULL;
UiInteger *rgroup;
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER);
UiBool first = FALSE;
if(var) {
@@ -432,9 +440,9 @@ UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) {
}
}
- GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args.label);
- ui_set_name_and_style(rbutton, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, rbutton, args.groups);
+ GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args->label);
+ ui_set_name_and_style(rbutton, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, rbutton, args->groups);
if(rgroup) {
#if GTK_MAJOR_VERSION >= 4
if(rg) {
@@ -476,13 +484,14 @@ UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) {
rbdata);
}
- if(args.onchange) {
+ if(args->onchange) {
UiEventData *event = malloc(sizeof(UiEventData));
event->obj = obj;
- event->userdata = args.onchangedata;
- event->callback = args.onchange;
+ event->userdata = args->onchangedata;
+ event->callback = args->onchange;
event->value = 0;
event->customdata = NULL;
+ event->customint = 0;
g_signal_connect(
rbutton,
@@ -496,8 +505,8 @@ UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) {
event);
}
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, rbutton, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, rbutton);
return rbutton;
}
@@ -510,6 +519,7 @@ void ui_radio_obs(GtkToggleButton *widget, UiVarEventData *event) {
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = i->get(i);
ui_notify_evt(i->observers, &e);
diff --git a/ui/gtk/container.c b/ui/gtk/container.c
index 41c7924..7a98bf4 100644
--- a/ui/gtk/container.c
+++ b/ui/gtk/container.c
@@ -120,12 +120,9 @@ UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType
return (UiContainer*)ct;
}
-void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_box_container_add(UiContainer *ct, GtkWidget *widget) {
UiBoxContainer *bc = (UiBoxContainer*)ct;
- if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
- fill = ui_lb2bool(ct->layout.fill);
- }
-
+ UiBool fill = ct->layout.fill;
if(bc->has_fill && fill) {
fprintf(stderr, "UiError: container has 2 filled widgets");
fill = FALSE;
@@ -180,7 +177,7 @@ UiContainer* ui_grid_container(
}
#if GTK_MAJOR_VERSION >= 3
-void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_grid_container_add(UiContainer *ct, GtkWidget *widget) {
UiGridContainer *grid = (UiGridContainer*)ct;
if(ct->layout.newline) {
@@ -208,9 +205,7 @@ void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
}
}
- if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
- fill = ui_lb2bool(ct->layout.fill);
- }
+ UiBool fill = ct->layout.fill;
if(ct->layout.hexpand) {
hexpand = TRUE;
hfill = TRUE;
@@ -249,7 +244,7 @@ void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
}
#endif
#ifdef UI_GTK2
-void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_grid_container_add(UiContainer *ct, GtkWidget *widget) {
UiGridContainer *grid = (UiGridContainer*)ct;
if(ct->layout.newline) {
@@ -277,9 +272,7 @@ void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
}
}
- if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
- fill = ui_lb2bool(ct->layout.fill);
- }
+ UiBool fill = ct->layout.fill;
if(ct->layout.hexpand) {
hexpand = TRUE;
hfill = TRUE;
@@ -340,7 +333,7 @@ UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame) {
return ct;
}
-void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_frame_container_add(UiContainer *ct, GtkWidget *widget) {
FRAME_SET_CHILD(ct->widget, widget);
}
@@ -354,11 +347,11 @@ UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander) {
return ct;
}
-void ui_expander_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_expander_container_add(UiContainer *ct, GtkWidget *widget) {
EXPANDER_SET_CHILD(ct->widget, widget);
}
-void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget) {
// TODO: check if the widget implements GtkScrollable
SCROLLEDWINDOW_SET_CHILD(ct->widget, widget);
ui_reset_layout(ct->layout);
@@ -385,7 +378,7 @@ UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview) {
return (UiContainer*)ct;
}
-void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget) {
UiGtkTabView *data = ui_widget_get_tabview_data(ct->widget);
if(!data) {
fprintf(stderr, "UI Error: widget is not a tabview");
@@ -420,15 +413,15 @@ GtkWidget* ui_box_set_margin(GtkWidget *box, int margin) {
return ret;
}
-UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType type) {
+UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType type) {
UiObject *current = uic_current_obj(obj);
UiContainer *ct = current->container;
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
- GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
- ui_set_name_and_style(box, args.name, args.style_class);
- GtkWidget *widget = args.margin > 0 ? ui_box_set_margin(box, args.margin) : box;
- ct->add(ct, widget, TRUE);
+ GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing);
+ ui_set_name_and_style(box, args->name, args->style_class);
+ GtkWidget *widget = args->margin > 0 ? ui_box_set_margin(box, args->margin) : box;
+ ct->add(ct, widget);
UiObject *newobj = uic_object_new(obj, box);
newobj->container = ui_box_container(obj, box, type);
@@ -437,11 +430,11 @@ UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType t
return widget;
}
-UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) {
+UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) {
return ui_box_create(obj, args, UI_CONTAINER_VBOX);
}
-UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) {
+UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) {
return ui_box_create(obj, args, UI_CONTAINER_HBOX);
}
@@ -458,74 +451,74 @@ GtkWidget* ui_create_grid_widget(int colspacing, int rowspacing) {
return grid;
}
-UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) {
+UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
UiObject* current = uic_current_obj(obj);
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
GtkWidget *widget;
- GtkWidget *grid = ui_create_grid_widget(args.columnspacing, args.rowspacing);
- ui_set_name_and_style(grid, args.name, args.style_class);
- widget = ui_box_set_margin(grid, args.margin);
- current->container->add(current->container, widget, TRUE);
+ GtkWidget *grid = ui_create_grid_widget(args->columnspacing, args->rowspacing);
+ ui_set_name_and_style(grid, args->name, args->style_class);
+ widget = ui_box_set_margin(grid, args->margin);
+ current->container->add(current->container, widget);
UiObject *newobj = uic_object_new(obj, grid);
- newobj->container = ui_grid_container(obj, grid, args.def_hexpand, args.def_vexpand, args.def_hfill, args.def_vfill);
+ newobj->container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
uic_obj_add(obj, newobj);
return widget;
}
-UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs args) {
+UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
UiObject* current = uic_current_obj(obj);
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
- GtkWidget *frame = gtk_frame_new(args.label);
+ GtkWidget *frame = gtk_frame_new(args->label);
UiObject *newobj = uic_object_new(obj, frame);
- GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
+ GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin);
if(sub) {
FRAME_SET_CHILD(frame, sub);
} else {
newobj->widget = frame;
newobj->container = ui_frame_container(obj, frame);
}
- current->container->add(current->container, frame, FALSE);
+ current->container->add(current->container, frame);
uic_obj_add(obj, newobj);
return frame;
}
-UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs args) {
+UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) {
UiObject* current = uic_current_obj(obj);
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
- GtkWidget *expander = gtk_expander_new(args.label);
- gtk_expander_set_expanded(GTK_EXPANDER(expander), args.isexpanded);
+ GtkWidget *expander = gtk_expander_new(args->label);
+ gtk_expander_set_expanded(GTK_EXPANDER(expander), args->isexpanded);
UiObject *newobj = uic_object_new(obj, expander);
- GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
+ GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin);
if(sub) {
EXPANDER_SET_CHILD(expander, sub);
} else {
newobj->widget = expander;
newobj->container = ui_expander_container(obj, expander);
}
- current->container->add(current->container, expander, FALSE);
+ current->container->add(current->container, expander);
uic_obj_add(obj, newobj);
return expander;
}
-UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs args) {
+UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) {
UiObject* current = uic_current_obj(obj);
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
GtkWidget *sw = SCROLLEDWINDOW_NEW();
- ui_set_name_and_style(sw, args.name, args.style_class);
- GtkWidget *widget = ui_box_set_margin(sw, args.margin);
- current->container->add(current->container, widget, TRUE);
+ ui_set_name_and_style(sw, args->name, args->style_class);
+ GtkWidget *widget = ui_box_set_margin(sw, args->margin);
+ current->container->add(current->container, widget);
UiObject *newobj = uic_object_new(obj, sw);
- GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
+ GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin);
if(sub) {
SCROLLEDWINDOW_SET_CHILD(sw, sub);
} else {
@@ -689,22 +682,71 @@ UiGtkTabView* ui_widget_get_tabview_data(UIWIDGET tabview) {
return g_object_get_data(G_OBJECT(tabview), "ui_tabview");
}
+static void tabview_switch_page(
+ GtkNotebook *self,
+ GtkWidget *page,
+ guint page_num,
+ gpointer userdata)
+{
+ UiGtkTabView *tabview = userdata;
+ if(!tabview->onchange) {
+ return;
+ }
+
+ UiEvent event;
+ event.obj = tabview->obj;
+ event.window = event.obj->window;
+ event.document = event.obj->ctx->document;
+ event.set = ui_get_setop();
+ event.eventdata = NULL;
+ event.eventdatatype = 0;
+ event.intval = page_num;
+
+ tabview->onchange(&event, tabview->onchange);
+}
+
+#if GTK_CHECK_VERSION(3, 10, 0)
+
+static void tabview_stack_changed(
+ GObject *object,
+ GParamSpec *pspec,
+ UiGtkTabView *tabview)
+{
+ if(!tabview->onchange) {
+ return;
+ }
+
+ UiEvent event;
+ event.obj = tabview->obj;
+ event.window = event.obj->window;
+ event.document = event.obj->ctx->document;
+ event.set = ui_get_setop();
+ event.eventdata = NULL;
+ event.eventdatatype = 0;
+ event.intval = 0;
+
+ tabview->onchange(&event, tabview->onchange);
+}
+
+#endif
+
typedef int64_t(*ui_tabview_get_func)(UiInteger*);
typedef void (*ui_tabview_set_func)(UiInteger*, int64_t);
-UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
+UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) {
UiGtkTabView *data = malloc(sizeof(UiGtkTabView));
- data->margin = args.margin;
- data->spacing = args.spacing;
- data->columnspacing = args.columnspacing;
- data->rowspacing = args.rowspacing;
+ memset(data, 0, sizeof(UiGtkTabView));
+ data->margin = args->margin;
+ data->spacing = args->spacing;
+ data->columnspacing = args->columnspacing;
+ data->rowspacing = args->rowspacing;
ui_tabview_get_func getfunc = NULL;
ui_tabview_set_func setfunc = NULL;
GtkWidget *widget = NULL;
GtkWidget *data_widget = NULL;
- switch(args.tabview) {
+ switch(args->tabview) {
case UI_TABVIEW_DOC: {
// TODO
break;
@@ -715,6 +757,7 @@ UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
GtkWidget *sidebar = gtk_stack_sidebar_new();
BOX_ADD(widget, sidebar);
GtkWidget *stack = gtk_stack_new();
+ g_signal_connect(stack, "notify::visible-child", G_CALLBACK(tabview_stack_changed), data);
gtk_stack_set_transition_type (GTK_STACK(stack), GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
gtk_stack_sidebar_set_stack(GTK_STACK_SIDEBAR(sidebar), GTK_STACK(stack));
BOX_ADD_EXPAND(widget, stack);
@@ -734,13 +777,18 @@ UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
case UI_TABVIEW_INVISIBLE: /* fall through */
case UI_TABVIEW_NAVIGATION_TOP2: {
widget = gtk_notebook_new();
+ g_signal_connect(
+ widget,
+ "switch-page",
+ G_CALLBACK(tabview_switch_page),
+ data);
data_widget = widget;
data->select_tab = ui_notebook_tab_select;
data->remove_tab = ui_notebook_tab_remove;
data->add_tab = ui_notebook_tab_add;
getfunc = ui_notebook_get;
setfunc = ui_notebook_set;
- if(args.tabview == UI_TABVIEW_INVISIBLE) {
+ if(args->tabview == UI_TABVIEW_INVISIBLE) {
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(widget), FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK(widget), FALSE);
}
@@ -749,8 +797,8 @@ UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
}
UiObject* current = uic_current_obj(obj);
- if(args.value || args.varname) {
- UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
+ if(args->value || args->varname) {
+ UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER);
UiInteger *i = var->value;
i->get = getfunc;
i->set = setfunc;
@@ -759,10 +807,10 @@ UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
g_object_set_data(G_OBJECT(widget), "ui_tabview", data);
data->widget = data_widget;
- data->subcontainer = args.subcontainer;
+ data->subcontainer = args->subcontainer;
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, widget, TRUE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, widget);
UiObject *newobj = uic_object_new(obj, widget);
newobj->container = ui_tabview_container(obj, widget);
@@ -872,14 +920,14 @@ void ui_headerbar_end_create(UiObject *obj) {
hb_set_part(obj, 1);
}
-UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs args) {
+UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs *args) {
UiObject *current = uic_current_obj(obj);
UiContainer *ct = current->container;
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
- GtkWidget *box = ui_gtk_hbox_new(args.alt_spacing);
- ui_set_name_and_style(box, args.name, args.style_class);
- ct->add(ct, box, FALSE);
+ GtkWidget *box = ui_gtk_hbox_new(args->alt_spacing);
+ ui_set_name_and_style(box, args->name, args->style_class);
+ ct->add(ct, box);
UiObject *newobj = uic_object_new(obj, box);
newobj->container = ui_headerbar_fallback_container(obj, box);
@@ -910,14 +958,14 @@ UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar
return (UiContainer*)ct;
}
-void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget) {
UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
BOX_ADD(ct->widget, widget);
}
#if GTK_CHECK_VERSION(3, 10, 0)
-UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
+UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) {
GtkWidget *headerbar = g_object_get_data(G_OBJECT(obj->widget), "ui_headerbar");
if(!headerbar) {
return ui_headerbar_fallback_create(obj, args);
@@ -940,7 +988,7 @@ UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
return (UiContainer*)ct;
}
-void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget) {
UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
if(hb->part == 0) {
UI_HEADERBAR_PACK_START(ct->widget, widget);
@@ -958,7 +1006,7 @@ void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill)
#else
-UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
+UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) {
return ui_headerbar_fallback_create(obj, args);
}
@@ -967,15 +1015,15 @@ UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
/* -------------------- Sidebar -------------------- */
#ifdef UI_LIBADWAITA
-UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) {
+UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) {
GtkWidget *sidebar_toolbar_view = g_object_get_data(G_OBJECT(obj->widget), "ui_sidebar");
if(!sidebar_toolbar_view) {
fprintf(stderr, "Error: window is not configured for sidebar\n");
return NULL;
}
- GtkWidget *box = ui_gtk_vbox_new(args.spacing);
- ui_box_set_margin(box, args.margin);
+ GtkWidget *box = ui_gtk_vbox_new(args->spacing);
+ ui_box_set_margin(box, args->margin);
adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), box);
UiObject *newobj = uic_object_new(obj, box);
@@ -985,11 +1033,11 @@ UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) {
return box;
}
#else
-UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) {
+UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) {
GtkWidget *sidebar_vbox = g_object_get_data(G_OBJECT(obj->widget), "ui_sidebar");
- GtkWidget *box = ui_gtk_vbox_new(args.spacing);
- ui_box_set_margin(box, args.margin);
+ GtkWidget *box = ui_gtk_vbox_new(args->spacing);
+ ui_box_set_margin(box, args->margin);
BOX_ADD_EXPAND(sidebar_vbox, box);
UiObject *newobj = uic_object_new(obj, box);
@@ -1019,18 +1067,18 @@ static GtkWidget* create_paned(UiOrientation orientation) {
-static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs args) {
+static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs *args) {
UiObject* current = uic_current_obj(obj);
GtkWidget *pane0 = create_paned(orientation);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, pane0, TRUE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, pane0);
- int max = args.max_panes == 0 ? 2 : args.max_panes;
+ int max = args->max_panes == 0 ? 2 : args->max_panes;
UiObject *newobj = uic_object_new(obj, pane0);
- newobj->container = ui_splitpane_container(obj, pane0, orientation, max, args.initial_position);
+ newobj->container = ui_splitpane_container(obj, pane0, orientation, max, args->initial_position);
uic_obj_add(obj, newobj);
g_object_set_data(G_OBJECT(pane0), "ui_splitpane", newobj->container);
@@ -1038,11 +1086,11 @@ static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSpl
return pane0;
}
-UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
+UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs *args) {
return splitpane_create(obj, UI_HORIZONTAL, args);
}
-UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
+UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs *args) {
return splitpane_create(obj, UI_VERTICAL, args);
}
@@ -1058,7 +1106,7 @@ UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientatio
return (UiContainer*)ct;
}
-void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget) {
UiSplitPaneContainer *s = (UiSplitPaneContainer*)ct;
if(s->nchildren >= s->max) {
@@ -1151,7 +1199,7 @@ static void update_itemlist(UiList *list, int c) {
UiObject *item_obj = cxMapGet(ct->current_items, key);
if(item_obj) {
// re-add previously created widget
- ui_box_container_add(ct->container, item_obj->widget, FALSE);
+ ui_box_container_add(ct->container, item_obj->widget);
} else {
// create new widget and object for this list element
CxMempool *mp = cxMempoolCreateSimple(256);
@@ -1166,7 +1214,7 @@ static void update_itemlist(UiList *list, int c) {
ct->columnspacing,
ct->rowspacing,
ct->margin);
- ui_box_container_add(ct->container, obj->widget, FALSE);
+ ui_box_container_add(ct->container, obj->widget);
if(ct->create_ui) {
ct->create_ui(obj, index, elm, ct->userdata);
}
@@ -1187,33 +1235,33 @@ static void destroy_itemlist_container(GtkWidget *w, UiGtkItemListContainer *con
free(container);
}
-UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args) {
+UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs *args) {
UiObject *current = uic_current_obj(obj);
UiContainer *ct = current->container;
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
- GtkWidget *box = args.container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
- ui_set_name_and_style(box, args.name, args.style_class);
- GtkWidget *widget = args.margin > 0 ? ui_box_set_margin(box, args.margin) : box;
- ct->add(ct, widget, TRUE);
+ GtkWidget *box = args->container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing);
+ ui_set_name_and_style(box, args->name, args->style_class);
+ GtkWidget *widget = args->margin > 0 ? ui_box_set_margin(box, args->margin) : box;
+ ct->add(ct, widget);
UiGtkItemListContainer *container = malloc(sizeof(UiGtkItemListContainer));
container->parent = obj;
container->widget = box;
- container->container = ui_box_container(current, box, args.container);
- container->create_ui = args.create_ui;
- container->userdata = args.userdata;
- container->subcontainer = args.subcontainer;
+ container->container = ui_box_container(current, box, args->container);
+ container->create_ui = args->create_ui;
+ container->userdata = args->userdata;
+ container->subcontainer = args->subcontainer;
container->current_items = cxHashMapCreateSimple(CX_STORE_POINTERS);
container->current_items->collection.advanced_destructor = remove_item;
container->current_items->collection.destructor_data = container;
- container->margin = args.sub_margin;
- container->spacing = args.sub_spacing;
- container->columnspacing = args.sub_columnspacing;
- container->rowspacing = args.sub_rowspacing;
+ container->margin = args->sub_margin;
+ container->spacing = args->sub_spacing;
+ container->columnspacing = args->sub_columnspacing;
+ container->rowspacing = args->sub_rowspacing;
container->remove_items = TRUE;
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_LIST);
if(var) {
UiList *list = var->value;
list->obj = container;
@@ -1240,7 +1288,7 @@ UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args) {
void ui_layout_fill(UiObject *obj, UiBool fill) {
UiContainer *ct = uic_get_current_container(obj);
- ct->layout.fill = ui_bool2lb(fill);
+ ct->layout.fill = fill;
}
void ui_layout_hexpand(UiObject *obj, UiBool expand) {
diff --git a/ui/gtk/container.h b/ui/gtk/container.h
index b39a3e4..5f44766 100644
--- a/ui/gtk/container.h
+++ b/ui/gtk/container.h
@@ -44,23 +44,15 @@ extern "C" {
#endif
#define ui_reset_layout(layout) memset(&(layout), 0, sizeof(UiLayout))
-#define ui_lb2bool(b) ((b) == UI_LAYOUT_TRUE ? TRUE : FALSE)
-#define ui_bool2lb(b) ((b) ? UI_LAYOUT_TRUE : UI_LAYOUT_FALSE)
-typedef void (*ui_container_add_f)(UiContainer*, GtkWidget*, UiBool);
+typedef void (*ui_container_add_f)(UiContainer*, GtkWidget*);
typedef struct UiDocumentView UiDocumentView;
-typedef enum UiLayoutBool {
- UI_LAYOUT_UNDEFINED = 0,
- UI_LAYOUT_TRUE,
- UI_LAYOUT_FALSE,
-} UiLayoutBool;
-
typedef struct UiLayout UiLayout;
struct UiLayout {
- UiLayoutBool fill;
+ UiBool fill;
UiBool newline;
char *label;
UiBool hexpand;
@@ -78,7 +70,7 @@ struct UiContainer {
UIMENU menu;
GtkWidget *current;
- void (*add)(UiContainer*, GtkWidget*, UiBool);
+ void (*add)(UiContainer*, GtkWidget*);
UiLayout layout;
int close;
@@ -122,6 +114,8 @@ typedef struct UiGtkTabView {
int spacing;
int columnspacing;
int rowspacing;
+ ui_callback onchange;
+ void *onchangedata;
} UiGtkTabView;
@@ -170,13 +164,13 @@ GtkWidget* ui_subcontainer_create(
int margin);
UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame);
-void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_frame_container_add(UiContainer *ct, GtkWidget *widget);
GtkWidget* ui_box_set_margin(GtkWidget *box, int margin);
-UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType type);
+UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType type);
UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type);
-void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_box_container_add(UiContainer *ct, GtkWidget *widget);
GtkWidget* ui_create_grid_widget(int colspacing, int rowspacing);
UiContainer* ui_grid_container(
@@ -186,22 +180,22 @@ UiContainer* ui_grid_container(
UiBool def_vexpand,
UiBool def_hfill,
UiBool def_vfill);
-void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_grid_container_add(UiContainer *ct, GtkWidget *widget);
UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame);
-void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_frame_container_add(UiContainer *ct, GtkWidget *widget);
UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander);
-void ui_expander_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_expander_container_add(UiContainer *ct, GtkWidget *widget);
UiContainer* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow);
-void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget);
UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview);
-void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget);
UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientation orientation, int max, int init);
-void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget);
UiGtkTabView* ui_widget_get_tabview_data(UIWIDGET tabview);
@@ -210,11 +204,11 @@ void ui_gtk_notebook_select_tab(GtkWidget *widget, int tab);
#if GTK_CHECK_VERSION(3, 10, 0)
UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar);
-void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget);
#endif
UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar);
-void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget);
#ifdef __cplusplus
}
diff --git a/ui/gtk/display.c b/ui/gtk/display.c
index 78ff754..40fcde1 100644
--- a/ui/gtk/display.c
+++ b/ui/gtk/display.c
@@ -46,19 +46,19 @@ static void set_alignment(GtkWidget *widget, float xalign, float yalign) {
#endif
}
-UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) {
+UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs *args) {
UiObject* current = uic_current_obj(obj);
const char *css_class = NULL;
char *markup = NULL;
- if(args.label) {
+ if(args->label) {
#if GTK_MAJOR_VERSION < 3
- switch(args.style) {
+ switch(args->style) {
case UI_LABEL_STYLE_DEFAULT: break;
case UI_LABEL_STYLE_TITLE: {
- cxmutstr m = cx_asprintf("%s", args.label);
+ cxmutstr m = cx_asprintf("%s", args->label);
markup = m.ptr;
- args.label = NULL;
+ args->label = NULL;
}
case UI_LABEL_STYLE_SUBTITLE: {
break;
@@ -68,7 +68,7 @@ UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) {
}
}
# else
- switch(args.style) {
+ switch(args->style) {
case UI_LABEL_STYLE_DEFAULT: break;
case UI_LABEL_STYLE_TITLE: {
css_class = "ui_label_title";
@@ -87,7 +87,7 @@ UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) {
}
- GtkWidget *widget = gtk_label_new(args.label);
+ GtkWidget *widget = gtk_label_new(args->label);
if(markup) {
gtk_label_set_markup(GTK_LABEL(widget), markup);
free(markup);
@@ -97,7 +97,7 @@ UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) {
WIDGET_ADD_CSS_CLASS(widget, css_class);
}
- switch(args.align) {
+ switch(args->align) {
case UI_ALIGN_DEFAULT: break;
case UI_ALIGN_LEFT: set_alignment(widget, 0, .5); break;
case UI_ALIGN_RIGHT: set_alignment(widget, 1, .5); break;
@@ -105,7 +105,7 @@ UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) {
}
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING);
if(var) {
UiString* value = (UiString*)var->value;
value->obj = widget;
@@ -113,19 +113,19 @@ UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) {
value->set = ui_label_set;
}
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, widget, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, widget);
return widget;
}
-UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args) {
- args.align = UI_ALIGN_LEFT;
+UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs *args) {
+ args->align = UI_ALIGN_LEFT;
return ui_label_create(obj, args);
}
-UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args) {
- args.align = UI_ALIGN_RIGHT;
+UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs *args) {
+ args->align = UI_ALIGN_RIGHT;
return ui_label_create(obj, args);
}
@@ -150,7 +150,7 @@ void ui_label_set(UiString *s, const char *value) {
UIWIDGET ui_space_deprecated(UiObject *obj) {
GtkWidget *widget = gtk_label_new("");
UiContainer *ct = uic_get_current_container(obj);
- ct->add(ct, widget, TRUE);
+ ct->add(ct, widget);
return widget;
}
@@ -162,7 +162,7 @@ UIWIDGET ui_separator_deprecated(UiObject *obj) {
GtkWidget *widget = gtk_hseparator_new();
#endif
UiContainer *ct = uic_get_current_container(obj);
- ct->add(ct, widget, FALSE);
+ ct->add(ct, widget);
return widget;
}
@@ -174,14 +174,14 @@ typedef struct UiProgressBarRange {
double max;
} UiProgressBarRange;
-UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) {
+UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs *args) {
UiObject* current = uic_current_obj(obj);
GtkWidget *progressbar = gtk_progress_bar_new();
- if(args.max > args.min) {
+ if(args->max > args->min) {
UiProgressBarRange *range = malloc(sizeof(UiProgressBarRange));
- range->min = args.min;
- range->max = args.max;
+ range->min = args->min;
+ range->max = args->max;
g_signal_connect(
progressbar,
"destroy",
@@ -191,7 +191,7 @@ UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) {
}
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_DOUBLE);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_DOUBLE);
if(var && var->value) {
UiDouble *value = var->value;
value->get = ui_progressbar_get;
@@ -200,8 +200,8 @@ UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) {
ui_progressbar_set(value, value->value);
}
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, progressbar, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, progressbar);
return progressbar;
}
@@ -228,12 +228,12 @@ void ui_progressbar_set(UiDouble *d, double value) {
/* ------------------------- progress spinner ------------------------- */
-UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args) {
+UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs *args) {
UiObject* current = uic_current_obj(obj);
GtkWidget *spinner = gtk_spinner_new();
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER);
if(var && var->value) {
UiInteger *value = var->value;
value->get = ui_spinner_get;
@@ -242,8 +242,8 @@ UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args)
ui_spinner_set(value, value->value);
}
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, spinner, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, spinner);
return spinner;
}
diff --git a/ui/gtk/entry.c b/ui/gtk/entry.c
index 38ebe17..3c83f11 100644
--- a/ui/gtk/entry.c
+++ b/ui/gtk/entry.c
@@ -35,24 +35,24 @@
#include "entry.h"
-UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs args) {
+UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs *args) {
double min = 0;
double max = 1000;
UiObject* current = uic_current_obj(obj);
UiVar *var = NULL;
- if(args.varname) {
- var = uic_get_var(obj->ctx, args.varname);
+ if(args->varname) {
+ var = uic_get_var(obj->ctx, args->varname);
}
if(!var) {
- if(args.intvalue) {
- var = uic_widget_var(obj->ctx, current->ctx, args.intvalue, NULL, UI_VAR_INTEGER);
- } else if(args.doublevalue) {
- var = uic_widget_var(obj->ctx, current->ctx, args.doublevalue, NULL, UI_VAR_DOUBLE);
- } else if(args.rangevalue) {
- var = uic_widget_var(obj->ctx, current->ctx, args.rangevalue, NULL, UI_VAR_RANGE);
+ if(args->intvalue) {
+ var = uic_widget_var(obj->ctx, current->ctx, args->intvalue, NULL, UI_VAR_INTEGER);
+ } else if(args->doublevalue) {
+ var = uic_widget_var(obj->ctx, current->ctx, args->doublevalue, NULL, UI_VAR_DOUBLE);
+ } else if(args->rangevalue) {
+ var = uic_widget_var(obj->ctx, current->ctx, args->rangevalue, NULL, UI_VAR_RANGE);
}
}
@@ -61,18 +61,18 @@ UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs args) {
min = r->min;
max = r->max;
}
- if(args.step == 0) {
- args.step = 1;
+ if(args->step == 0) {
+ args->step = 1;
}
#ifdef UI_GTK2LEGACY
if(min == max) {
max = min + 1;
}
#endif
- GtkWidget *spin = gtk_spin_button_new_with_range(min, max, args.step);
- ui_set_name_and_style(spin, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, spin, args.groups);
- gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), args.digits);
+ GtkWidget *spin = gtk_spin_button_new_with_range(min, max, args->step);
+ ui_set_name_and_style(spin, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, spin, args->groups);
+ gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), args->digits);
UiObserver **obs = NULL;
if(var) {
double value = 0;
@@ -115,8 +115,8 @@ UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs args) {
event->obj = obj;
event->var = var;
event->observers = obs;
- event->callback = args.onchange;
- event->userdata = args.onchangedata;
+ event->callback = args->onchange;
+ event->userdata = args->onchangedata;
g_signal_connect(
spin,
@@ -129,8 +129,8 @@ UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs args) {
G_CALLBACK(ui_destroy_vardata),
event);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, spin, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, spin);
return spin;
}
@@ -150,7 +150,8 @@ void ui_spinner_changed(GtkSpinButton *spinner, UiVarEventData *event) {
e.obj = event->obj;
e.window = event->obj->window;
e.document = event->obj->ctx->document;
- e.eventdata = &value;
+ e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = (int64_t)value;
if(event->callback) {
diff --git a/ui/gtk/graphics.c b/ui/gtk/graphics.c
index dcaff88..6883575 100644
--- a/ui/gtk/graphics.c
+++ b/ui/gtk/graphics.c
@@ -45,7 +45,7 @@ UIWIDGET ui_drawingarea(UiObject *obj, ui_drawfunc f, void *userdata) {
}
UiContainer *ct = uic_get_current_container(obj);
- ct->add(ct, widget, TRUE);
+ ct->add(ct, widget);
return widget;
}
diff --git a/ui/gtk/image.c b/ui/gtk/image.c
index ea2f6bb..425af82 100644
--- a/ui/gtk/image.c
+++ b/ui/gtk/image.c
@@ -63,7 +63,7 @@ static gboolean imageviewer_draw(GtkWidget *widget, cairo_t *cr, gpointer userda
#endif
-UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
+UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs *args) {
UiObject *current = uic_current_obj(obj);
GtkWidget *drawingarea = gtk_drawing_area_new();
@@ -78,10 +78,10 @@ UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
widget = eventbox;
#endif
- if(args.scrollarea) {
+ if(args->scrollarea) {
toplevel = SCROLLEDWINDOW_NEW();
SCROLLEDWINDOW_SET_CHILD(toplevel, widget);
- args.adjustwidgetsize = TRUE;
+ args->adjustwidgetsize = TRUE;
} else {
toplevel = widget;
}
@@ -89,29 +89,29 @@ UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
UiImageViewer *imgviewer = malloc(sizeof(UiImageViewer));
memset(imgviewer, 0, sizeof(UiImageViewer));
imgviewer->obj = obj;
- imgviewer->onbuttonpress = args.onbuttonpress;
- imgviewer->onbuttonpressdata = args.onbuttonpressdata;
- imgviewer->onbuttonrelease = args.onbuttonrelease;
- imgviewer->onbuttonreleasedata = args.onbuttonreleasedata;
- if(args.image_padding > 0) {
- imgviewer->padding_left = args.image_padding;
- imgviewer->padding_right = args.image_padding;
- imgviewer->padding_top = args.image_padding;
- imgviewer->padding_bottom = args.image_padding;
+ imgviewer->onbuttonpress = args->onbuttonpress;
+ imgviewer->onbuttonpressdata = args->onbuttonpressdata;
+ imgviewer->onbuttonrelease = args->onbuttonrelease;
+ imgviewer->onbuttonreleasedata = args->onbuttonreleasedata;
+ if(args->image_padding > 0) {
+ imgviewer->padding_left = args->image_padding;
+ imgviewer->padding_right = args->image_padding;
+ imgviewer->padding_top = args->image_padding;
+ imgviewer->padding_bottom = args->image_padding;
} else {
- imgviewer->padding_left = args.image_padding_left;
- imgviewer->padding_right = args.image_padding_right;
- imgviewer->padding_top = args.image_padding_top;
- imgviewer->padding_bottom = args.image_padding_bottom;
+ imgviewer->padding_left = args->image_padding_left;
+ imgviewer->padding_right = args->image_padding_right;
+ imgviewer->padding_top = args->image_padding_top;
+ imgviewer->padding_bottom = args->image_padding_bottom;
}
- imgviewer->adjustwidgetsize = args.adjustwidgetsize;
- imgviewer->autoscale = args.autoscale;
- imgviewer->useradjustable = args.useradjustable;
+ imgviewer->adjustwidgetsize = args->adjustwidgetsize;
+ imgviewer->autoscale = args->autoscale;
+ imgviewer->useradjustable = args->useradjustable;
imgviewer->zoom_scale = 20;
g_object_set_data_full(G_OBJECT(drawingarea), "uiimageviewer", imgviewer, (GDestroyNotify)imageviewer_destroy);
- UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_GENERIC);
+ UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_GENERIC);
imgviewer->var = var;
imgviewer->widget = drawingarea;
@@ -136,7 +136,7 @@ UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
imgviewer,
NULL);
- if(args.useradjustable) {
+ if(args->useradjustable) {
gtk_widget_set_focusable(drawingarea, TRUE);
}
@@ -182,13 +182,13 @@ UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
#endif
- if(args.contextmenu) {
- UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, widget);
+ if(args->contextmenu) {
+ UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, widget);
ui_widget_set_contextmenu(widget, menu);
}
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, toplevel, TRUE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, toplevel);
return toplevel;
}
@@ -438,6 +438,7 @@ static void imgviewer_button_event(
event.window = event.obj->window;
event.document = event.obj->ctx->document;
event.eventdata = NULL;
+ event.eventdatatype = 0;
event.intval = gtk_gesture_single_get_current_button(GTK_GESTURE_SINGLE(gesture));
event.set = 0;
callback(&event, userdata);
diff --git a/ui/gtk/list.c b/ui/gtk/list.c
index 978ab53..be9c00a 100644
--- a/ui/gtk/list.c
+++ b/ui/gtk/list.c
@@ -48,6 +48,15 @@ void* ui_strmodel_getvalue(void *elm, int column) {
return column == 0 ? elm : NULL;
}
+static void* model_getvalue(UiModel *model, UiList *list, void *elm, int row, int col, UiBool *freeResult) {
+ if(model->getvalue2) {
+ return model->getvalue2(list, elm, row, col, model->getvalue2data, freeResult);
+ } else if(model->getvalue) {
+ return model->getvalue(elm, col);
+ }
+ return NULL;
+}
+
/*
static GtkTargetEntry targetentries[] =
{
@@ -73,6 +82,7 @@ static void listview_copy_static_elements(UiListView *listview, char **elm, size
typedef struct _ObjWrapper {
GObject parent_instance;
void *data;
+ int i;
} ObjWrapper;
typedef struct _ObjWrapperClass {
@@ -89,9 +99,10 @@ static void obj_wrapper_init(ObjWrapper *self) {
self->data = NULL;
}
-ObjWrapper* obj_wrapper_new(void* data) {
+ObjWrapper* obj_wrapper_new(void* data, int i) {
ObjWrapper *obj = g_object_new(obj_wrapper_get_type(), NULL);
obj->data = data;
+ obj->i = i;
return obj;
}
@@ -122,20 +133,21 @@ static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item,
static void column_factory_bind( GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) {
UiColData *col = userdata;
+ UiList *list = col->listview->var ? col->listview->var->value : NULL;
ObjWrapper *obj = gtk_list_item_get_item(item);
UiModel *model = col->listview->model;
UiModelType type = model->types[col->model_column];
- void *data = model->getvalue(obj->data, col->data_column);
+ UiBool freevalue = FALSE;
+ void *data = model_getvalue(model, list, obj->data, obj->i, col->data_column, &freevalue);
GtkWidget *child = gtk_list_item_get_child(item);
- bool freevalue = TRUE;
switch(type) {
- case UI_STRING: {
- freevalue = FALSE;
- }
case UI_STRING_FREE: {
+ freevalue = TRUE;
+ }
+ case UI_STRING: {
gtk_label_set_label(GTK_LABEL(child), data);
if(freevalue) {
free(data);
@@ -157,10 +169,13 @@ static void column_factory_bind( GtkListItemFactory *factory, GtkListItem *item,
break;
}
case UI_ICON_TEXT: {
- freevalue = FALSE;
+
}
case UI_ICON_TEXT_FREE: {
- void *data2 = model->getvalue(obj->data, col->data_column+1);
+ void *data2 = model_getvalue(model, list, obj->data, obj->i, col->data_column+1, &freevalue);
+ if(type == UI_ICON_TEXT_FREE) {
+ freevalue = TRUE;
+ }
GtkWidget *image = g_object_get_data(G_OBJECT(child), "image");
GtkWidget *label = g_object_get_data(G_OBJECT(child), "label");
if(data && image) {
@@ -189,34 +204,41 @@ static GtkSelectionModel* create_selection_model(UiListView *listview, GListStor
return selection_model;
}
-static UiListView* create_listview(UiObject *obj, UiListArgs args) {
+static UiListView* create_listview(UiObject *obj, UiListArgs *args) {
UiListView *tableview = malloc(sizeof(UiListView));
memset(tableview, 0, sizeof(UiListView));
tableview->obj = obj;
- tableview->model = args.model;
- tableview->onactivate = args.onactivate;
- tableview->onactivatedata = args.onactivatedata;
- tableview->onselection = args.onselection;
- tableview->onselectiondata = args.onselectiondata;
- tableview->ondragstart = args.ondragstart;
- tableview->ondragstartdata = args.ondragstartdata;
- tableview->ondragcomplete = args.ondragcomplete;
- tableview->ondragcompletedata = args.ondragcompletedata;
- tableview->ondrop = args.ondrop;
- tableview->ondropdata = args.ondropsdata;
+ tableview->model = args->model;
+ tableview->onactivate = args->onactivate;
+ tableview->onactivatedata = args->onactivatedata;
+ tableview->onselection = args->onselection;
+ tableview->onselectiondata = args->onselectiondata;
+ tableview->ondragstart = args->ondragstart;
+ tableview->ondragstartdata = args->ondragstartdata;
+ tableview->ondragcomplete = args->ondragcomplete;
+ tableview->ondragcompletedata = args->ondragcompletedata;
+ tableview->ondrop = args->ondrop;
+ tableview->ondropdata = args->ondropdata;
tableview->selection.count = 0;
tableview->selection.rows = NULL;
return tableview;
}
-UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
+UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
UiObject* current = uic_current_obj(obj);
// to simplify things and share code with ui_table_create, we also
// use a UiModel for the listview
UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
- model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
- args.model = model;
+ if(args->getvalue2) {
+ model->getvalue2 = args->getvalue2;
+ model->getvalue2data = args->getvalue2data;
+ } else if(args->getvalue) {
+ model->getvalue = args->getvalue;
+ } else {
+ model->getvalue = ui_strmodel_getvalue;
+ }
+ args->model = model;
GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
UiListView *listview = create_listview(obj, args);
@@ -230,10 +252,10 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns);
g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns);
- GtkSelectionModel *selection_model = create_selection_model(listview, ls, args.multiselection);
+ GtkSelectionModel *selection_model = create_selection_model(listview, ls, args->multiselection);
GtkWidget *view = gtk_list_view_new(GTK_SELECTION_MODEL(selection_model), factory);
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST);
// init listview
listview->widget = view;
@@ -256,21 +278,21 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
list->setselection = ui_listview_setselection2;
ui_update_liststore(ls, list);
- } else if (args.static_elements && args.static_nelm > 0) {
- listview_copy_static_elements(listview, args.static_elements, args.static_nelm);
+ } else if (args->static_elements && args->static_nelm > 0) {
+ listview_copy_static_elements(listview, args->static_elements, args->static_nelm);
listview->model->getvalue = ui_strmodel_getvalue; // force strmodel
ui_update_liststore_static(ls, listview->elements, listview->nelm);
}
// event handling
- if(args.onactivate) {
+ if(args->onactivate) {
// columnview and listview can use the same callback function, because
// the first parameter (which is technically a different pointer type)
// is ignored
g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), listview);
}
- if(args.contextmenu) {
- UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, view);
+ if(args->contextmenu) {
+ UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view);
ui_widget_set_contextmenu(view, menu);
}
@@ -282,8 +304,8 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS
SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, scroll_area, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, scroll_area);
// ct->current should point to view, not scroll_area, to make it possible
// to add a context menu
@@ -292,14 +314,21 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
return scroll_area;
}
-UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) {
+UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args) {
UiObject* current = uic_current_obj(obj);
// to simplify things and share code with ui_tableview_create, we also
// use a UiModel for the listview
UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
- model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
- args.model = model;
+ if(args->getvalue2) {
+ model->getvalue2 = args->getvalue2;
+ model->getvalue2data = args->getvalue2data;
+ } else if(args->getvalue) {
+ model->getvalue = args->getvalue;
+ } else {
+ model->getvalue = ui_strmodel_getvalue;
+ }
+ args->model = model;
GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
UiListView *listview = create_listview(obj, args);
@@ -316,7 +345,7 @@ UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) {
GtkWidget *view = gtk_drop_down_new(G_LIST_MODEL(ls), NULL);
gtk_drop_down_set_factory(GTK_DROP_DOWN(view), factory);
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST);
// init listview
listview->widget = view;
@@ -339,20 +368,20 @@ UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) {
list->setselection = ui_combobox_setselection;
ui_update_liststore(ls, list);
- } else if (args.static_elements && args.static_nelm > 0) {
- listview_copy_static_elements(listview, args.static_elements, args.static_nelm);
+ } else if (args->static_elements && args->static_nelm > 0) {
+ listview_copy_static_elements(listview, args->static_elements, args->static_nelm);
listview->model->getvalue = ui_strmodel_getvalue; // force strmodel
ui_update_liststore_static(ls, listview->elements, listview->nelm);
}
// event handling
- if(args.onactivate) {
+ if(args->onactivate) {
g_signal_connect(view, "notify::selected", G_CALLBACK(ui_dropdown_notify), listview);
}
// add widget to parent
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, view, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, view);
return view;
}
@@ -365,7 +394,7 @@ void ui_combobox_select(UIWIDGET dropdown, int index) {
gtk_drop_down_set_selected(GTK_DROP_DOWN(dropdown), index);
}
-UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
+UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
UiObject* current = uic_current_obj(obj);
GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
@@ -375,10 +404,10 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
// and list updates
UiListView *tableview = create_listview(obj, args);
- GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args.multiselection);
+ GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args->multiselection);
GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model));
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST);
// init tableview
tableview->widget = view;
@@ -393,7 +422,7 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
// create columns from UiModel
- UiModel *model = args.model;
+ UiModel *model = args->model;
int columns = model ? model->columns : 0;
tableview->columns = calloc(columns, sizeof(UiColData));
@@ -439,11 +468,11 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
}
// event handling
- if(args.onactivate) {
+ if(args->onactivate) {
g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), tableview);
}
- if(args.contextmenu) {
- UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, view);
+ if(args->contextmenu) {
+ UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view);
ui_widget_set_contextmenu(view, menu);
}
@@ -455,8 +484,8 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS
SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, scroll_area, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, scroll_area);
// ct->current should point to view, not scroll_area, to make it possible
// to add a context menu
@@ -482,6 +511,7 @@ static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
event.window = event.obj->window;
event.intval = view->selection.count;
event.eventdata = &view->selection;
+ event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION;
event.set = ui_get_setop();
if(cb) {
cb(&event, cbdata);
@@ -525,6 +555,7 @@ void ui_dropdown_notify(GtkWidget *dropdown, GObject *pspec, gpointer userdata)
event.window = event.obj->window;
event.intval = index;
event.eventdata = eventdata->data;
+ event.eventdatatype = UI_EVENT_DATA_LIST_ELM;
event.set = ui_get_setop();
view->onactivate(&event, view->onactivatedata);
}
@@ -562,6 +593,7 @@ void ui_dropdown_activate(GtkDropDown* self, gpointer userdata) {
event.window = event.obj->window;
event.intval = view->selection.count;
event.eventdata = &view->selection;
+ event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION;
event.set = ui_get_setop();
view->onactivate(&event, view->onactivatedata);
}
@@ -569,9 +601,10 @@ void ui_dropdown_activate(GtkDropDown* self, gpointer userdata) {
void ui_update_liststore(GListStore *liststore, UiList *list) {
g_list_store_remove_all(liststore);
+ int i = 0;
void *elm = list->first(list);
while(elm) {
- ObjWrapper *obj = obj_wrapper_new(elm);
+ ObjWrapper *obj = obj_wrapper_new(elm, i++);
g_list_store_append(liststore, obj);
elm = list->next(list);
}
@@ -580,7 +613,7 @@ void ui_update_liststore(GListStore *liststore, UiList *list) {
void ui_update_liststore_static(GListStore *liststore, char **elm, size_t nelm) {
g_list_store_remove_all(liststore);
for(int i=0;iget(list, i);
if(value) {
- ObjWrapper *obj = obj_wrapper_new(value);
+ ObjWrapper *obj = obj_wrapper_new(value, i);
// TODO: if index i is selected, the selection is lost
// is it possible to update the item without removing it?
int count = g_list_model_get_n_items(G_LIST_MODEL(view->liststore));
@@ -662,19 +695,22 @@ void ui_combobox_setselection(UiList *list, UiListSelection selection) {
#else
-static void update_list_row(GtkListStore *store, GtkTreeIter *iter, UiModel *model, void *elm) {
+static void update_list_row(GtkListStore *store, GtkTreeIter *iter, UiModel *model, UiList *list, void *elm, int row) {
// set column values
int c = 0;
for(int i=0;icolumns;i++,c++) {
- void *data = model->getvalue(elm, c);
+ UiBool freevalue = FALSE;
+ void *data = model_getvalue(model, list, elm, row, c, &freevalue);
GValue value = G_VALUE_INIT;
switch(model->types[i]) {
- case UI_STRING:
case UI_STRING_FREE: {
+ freevalue = TRUE;
+ }
+ case UI_STRING: {
g_value_init(&value, G_TYPE_STRING);
g_value_set_string(&value, data);
- if(model->types[i] == UI_STRING_FREE) {
+ if(freevalue) {
free(data);
}
break;
@@ -727,11 +763,12 @@ static void update_list_row(GtkListStore *store, GtkTreeIter *iter, UiModel *mod
}
#endif
c++;
-
- char *str = model->getvalue(elm, c);
+
+ freevalue = FALSE;
+ char *str = model_getvalue(model, list, elm, row, c, &freevalue);
g_value_init(&value, G_TYPE_STRING);
g_value_set_string(&value, str);
- if(model->types[i] == UI_ICON_TEXT_FREE) {
+ if(model->types[i] == UI_ICON_TEXT_FREE || freevalue) {
free(str);
}
break;
@@ -764,12 +801,13 @@ static GtkListStore* create_list_store(UiList *list, UiModel *model) {
if(list) {
void *elm = list->first(list);
+ int i = 0;
while(elm) {
// insert new row
GtkTreeIter iter;
gtk_list_store_insert (store, &iter, -1);
- update_list_row(store, &iter, model, elm);
+ update_list_row(store, &iter, model, list, elm, i++);
// next row
elm = list->next(list);
@@ -780,13 +818,13 @@ static GtkListStore* create_list_store(UiList *list, UiModel *model) {
}
-UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
+UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
UiObject* current = uic_current_obj(obj);
// create treeview
GtkWidget *view = gtk_tree_view_new();
- ui_set_name_and_style(view, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, view, args.groups);
+ ui_set_name_and_style(view, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, view, args->groups);
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(NULL, renderer, "text", 0, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
@@ -803,9 +841,16 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
#endif
UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
- model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
+ if(args->getvalue2) {
+ model->getvalue2 = args->getvalue2;
+ model->getvalue2data = args->getvalue2data;
+ } else if(args->getvalue) {
+ model->getvalue = args->getvalue;
+ } else {
+ model->getvalue = ui_strmodel_getvalue;
+ }
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST);
UiList *list = var ? var->value : NULL;
GtkListStore *listmodel = create_list_store(list, model);
@@ -835,24 +880,24 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
// add callback
UiTreeEventData *event = malloc(sizeof(UiTreeEventData));
event->obj = obj;
- event->activate = args.onactivate;
- event->activatedata = args.onactivatedata;
- event->selection = args.onselection;
- event->selectiondata = args.onselectiondata;
+ event->activate = args->onactivate;
+ event->activatedata = args->onactivatedata;
+ event->selection = args->onselection;
+ event->selectiondata = args->onselectiondata;
g_signal_connect(
view,
"destroy",
G_CALLBACK(ui_destroy_userdata),
event);
- if(args.onactivate) {
+ if(args->onactivate) {
g_signal_connect(
view,
"row-activated",
G_CALLBACK(ui_listview_activate_event),
event);
}
- if(args.onselection) {
+ if(args->onselection) {
GtkTreeSelection *selection = gtk_tree_view_get_selection(
GTK_TREE_VIEW(view));
g_signal_connect(
@@ -861,8 +906,8 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
G_CALLBACK(ui_listview_selection_event),
event);
}
- if(args.contextmenu) {
- UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, view);
+ if(args->contextmenu) {
+ UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view);
ui_widget_set_contextmenu(view, menu);
}
@@ -875,7 +920,7 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS
SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
current->container->add(current->container, scroll_area, FALSE);
// ct->current should point to view, not scroll_area, to make it possible
@@ -896,13 +941,13 @@ void ui_combobox_select(UIWIDGET dropdown, int index) {
gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), index);
}
-UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
+UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
UiObject* current = uic_current_obj(obj);
// create treeview
GtkWidget *view = gtk_tree_view_new();
- UiModel *model = args.model;
+ UiModel *model = args->model;
int columns = model ? model->columns : 0;
int addi = 0;
@@ -959,7 +1004,7 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
#endif
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST);
UiList *list = var ? var->value : NULL;
GtkListStore *listmodel = create_list_store(list, model);
@@ -977,12 +1022,12 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
tableview->widget = view;
tableview->var = var;
tableview->model = model;
- tableview->ondragstart = args.ondragstart;
- tableview->ondragstartdata = args.ondragstartdata;
- tableview->ondragcomplete = args.ondragcomplete;
- tableview->ondragcompletedata = args.ondragcompletedata;
- tableview->ondrop = args.ondrop;
- tableview->ondropdata = args.ondropsdata;
+ tableview->ondragstart = args->ondragstart;
+ tableview->ondragstartdata = args->ondragstartdata;
+ tableview->ondragcomplete = args->ondragcomplete;
+ tableview->ondragcompletedata = args->ondragcompletedata;
+ tableview->ondrop = args->ondrop;
+ tableview->ondropdata = args->ondropdata;
tableview->selection.count = 0;
tableview->selection.rows = NULL;
g_signal_connect(
@@ -1000,18 +1045,18 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
// add callback
UiTreeEventData *event = ui_malloc(obj->ctx, sizeof(UiTreeEventData));
event->obj = obj;
- event->activate = args.onactivate;
- event->selection = args.onselection;
- event->activatedata = args.onactivatedata;
- event->selectiondata = args.onselectiondata;
- if(args.onactivate) {
+ event->activate = args->onactivate;
+ event->selection = args->onselection;
+ event->activatedata = args->onactivatedata;
+ event->selectiondata = args->onselectiondata;
+ if(args->onactivate) {
g_signal_connect(
view,
"row-activated",
G_CALLBACK(ui_listview_activate_event),
event);
}
- if(args.onselection) {
+ if(args->onselection) {
GtkTreeSelection *selection = gtk_tree_view_get_selection(
GTK_TREE_VIEW(view));
g_signal_connect(
@@ -1023,15 +1068,15 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
// TODO: destroy callback
- if(args.ondragstart) {
- ui_listview_add_dnd(tableview, &args);
+ if(args->ondragstart) {
+ ui_listview_add_dnd(tableview, args);
}
- if(args.ondrop) {
- ui_listview_enable_drop(tableview, &args);
+ if(args->ondrop) {
+ ui_listview_enable_drop(tableview, args);
}
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view));
- if(args.multiselection) {
+ if(args->multiselection) {
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
}
@@ -1043,8 +1088,8 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS
SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
- if(args.contextmenu) {
- UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, scroll_area);
+ if(args->contextmenu) {
+ UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, scroll_area);
#if GTK_MAJOR_VERSION >= 4
ui_widget_set_contextmenu(scroll_area, menu);
#else
@@ -1052,7 +1097,7 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
#endif
}
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
current->container->add(current->container, scroll_area, FALSE);
// ct->current should point to view, not scroll_area, to make it possible
@@ -1075,7 +1120,7 @@ void ui_listview_update(UiList *list, int i) {
GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(view->widget));
GtkTreeIter iter;
if(gtk_tree_model_iter_nth_child(store, &iter, NULL, i)) {
- update_list_row(GTK_LIST_STORE(store), &iter, view->model, elm);
+ update_list_row(GTK_LIST_STORE(store), &iter, view->model, list, elm, i);
}
}
}
@@ -1102,18 +1147,25 @@ void ui_listview_setselection(UiList *list, UiListSelection selection) {
/* --------------------------- ComboBox --------------------------- */
-UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) {
+UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args) {
UiObject* current = uic_current_obj(obj);
UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
- model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
+ if(args->getvalue2) {
+ model->getvalue2 = args->getvalue2;
+ model->getvalue2data = args->getvalue2data;
+ } else if(args->getvalue) {
+ model->getvalue = args->getvalue;
+ } else {
+ model->getvalue = ui_strmodel_getvalue;
+ }
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST);
- GtkWidget *combobox = ui_create_combobox(obj, model, var, args.static_elements, args.static_nelm, args.onactivate, args.onactivatedata);
- ui_set_name_and_style(combobox, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, combobox, args.groups);
- UI_APPLY_LAYOUT1(current, args);
+ GtkWidget *combobox = ui_create_combobox(obj, model, var, args->static_elements, args->static_nelm, args->onactivate, args->onactivatedata);
+ ui_set_name_and_style(combobox, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, combobox, args->groups);
+ UI_APPLY_LAYOUT2(current, args);
current->container->add(current->container, combobox, FALSE);
current->container->current = combobox;
return combobox;
@@ -1336,6 +1388,7 @@ static GdkContentProvider *ui_listview_dnd_prepare(GtkDragSource *source, double
event.window = event.obj->window;
event.document = event.obj->ctx->document;
event.eventdata = dnd;
+ event.eventdatatype = UI_EVENT_DATA_DND;
event.intval = 0;
event.set = ui_get_setop();
listview->ondragstart(&event, listview->ondragstartdata);
@@ -1372,6 +1425,7 @@ static void ui_listview_drag_end(GtkDragSource *self, GdkDrag *drag, gboolean de
event.window = event.obj->window;
event.document = event.obj->ctx->document;
event.eventdata = &dnd;
+ event.eventdatatype = UI_EVENT_DATA_DND;
event.intval = 0;
event.set = ui_get_setop();
listview->ondragcomplete(&event, listview->ondragcompletedata);
@@ -1401,6 +1455,7 @@ static gboolean ui_listview_drop(
event.window = event.obj->window;
event.document = event.obj->ctx->document;
event.eventdata = &dnd;
+ event.eventdatatype = UI_EVENT_DATA_DND;
event.intval = 0;
event.set = ui_get_setop();
listview->ondrop(&event, listview->ondropdata);
@@ -1758,7 +1813,7 @@ static void add_sublist(UiListBox *uilistbox, CxList *sublists, UiSubList *subli
cxListAdd(sublists, &uisublist);
}
-UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) {
+UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args) {
UiObject* current = uic_current_obj(obj);
#ifdef UI_GTK3
@@ -1766,7 +1821,7 @@ UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) {
#else
GtkWidget *listbox = gtk_list_box_new();
#endif
- if(!args.style_class) {
+ if(!args->style_class) {
#if GTK_MAJOR_VERSION >= 4
WIDGET_ADD_CSS_CLASS(listbox, "navigation-sidebar");
#else
@@ -1777,31 +1832,32 @@ UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) {
GtkWidget *scroll_area = SCROLLEDWINDOW_NEW();
SCROLLEDWINDOW_SET_CHILD(scroll_area, listbox);
- ui_set_name_and_style(listbox, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, listbox, args.groups);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, scroll_area, TRUE);
+ ui_set_name_and_style(listbox, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, listbox, args->groups);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, scroll_area);
UiListBox *uilistbox = malloc(sizeof(UiListBox));
uilistbox->obj = obj;
uilistbox->listbox = GTK_LIST_BOX(listbox);
- uilistbox->getvalue = args.getvalue;
- uilistbox->onactivate = args.onactivate;
- uilistbox->onactivatedata = args.onactivatedata;
- uilistbox->onbuttonclick = args.onbuttonclick;
- uilistbox->onbuttonclickdata = args.onbuttonclickdata;
+ uilistbox->getvalue = args->getvalue;
+ uilistbox->getvaluedata = args->getvaluedata;
+ uilistbox->onactivate = args->onactivate;
+ uilistbox->onactivatedata = args->onactivatedata;
+ uilistbox->onbuttonclick = args->onbuttonclick;
+ uilistbox->onbuttonclickdata = args->onbuttonclickdata;
uilistbox->sublists = cxArrayListCreateSimple(sizeof(UiListBoxSubList), 4);
uilistbox->sublists->collection.advanced_destructor = (cx_destructor_func2)sublist_destroy;
uilistbox->sublists->collection.destructor_data = obj;
uilistbox->first_row = NULL;
- if(args.sublists) {
+ if(args->sublists) {
// static sublist initalization
- if(args.numsublists == 0 && args.sublists) {
- args.numsublists = INT_MAX;
+ if(args->numsublists == 0 && args->sublists) {
+ args->numsublists = INT_MAX;
}
- for(int i=0;inumsublists;i++) {
+ UiSubList sublist = args->sublists[i];
if(!sublist.varname && !sublist.value) {
break;
}
@@ -1812,7 +1868,7 @@ UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) {
// fill items
ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists));
} else {
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.dynamic_sublist, args.varname, UI_VAR_LIST);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->dynamic_sublist, args->varname, UI_VAR_LIST);
if(var) {
UiList *list = var->value;
list->obj = uilistbox;
@@ -1834,7 +1890,7 @@ UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) {
G_CALLBACK(ui_destroy_sourcelist),
uilistbox);
- if(args.onactivate) {
+ if(args->onactivate) {
g_signal_connect(
listbox,
"row-activated",
@@ -1958,7 +2014,11 @@ void ui_listbox_update_sublist(UiListBox *listbox, UiListBoxSubList *sublist, si
void *elm = list->first(list);
while(elm) {
UiSubListItem item = { NULL, NULL, NULL, NULL, NULL, NULL };
- listbox->getvalue(sublist->userdata, elm, index, &item);
+ if(listbox->getvalue) {
+ listbox->getvalue(list, sublist->userdata, elm, index, &item, listbox->getvaluedata);
+ } else {
+ item.label = strdup(elm);
+ }
// create listbox item
GtkWidget *row = create_listbox_row(listbox, sublist, &item, (int)index);
@@ -2009,7 +2069,7 @@ void ui_listbox_row_activate(GtkListBox *self, GtkListBoxRow *row, gpointer user
eventdata.sublist_index = sublist->index;
eventdata.row_index = data->value0;
eventdata.sublist_userdata = sublist->userdata;
- eventdata.row_data = ui_list_get(eventdata.list, eventdata.row_index);
+ eventdata.row_data = eventdata.list->get(eventdata.list, eventdata.row_index);
eventdata.event_data = data->customdata2;
UiEvent event;
@@ -2017,6 +2077,7 @@ void ui_listbox_row_activate(GtkListBox *self, GtkListBoxRow *row, gpointer user
event.window = event.obj->window;
event.document = event.obj->ctx->document;
event.eventdata = &eventdata;
+ event.eventdatatype = UI_EVENT_DATA_SUBLIST;
event.intval = data->value0;
event.set = ui_get_setop();
diff --git a/ui/gtk/list.h b/ui/gtk/list.h
index 784e644..bd490ab 100644
--- a/ui/gtk/list.h
+++ b/ui/gtk/list.h
@@ -98,6 +98,7 @@ struct UiListBox {
GtkListBox *listbox;
CxList *sublists; // contains UiListBoxSubList elements
ui_sublist_getvalue_func getvalue;
+ void *getvaluedata;
ui_callback onactivate;
void *onactivatedata;
ui_callback onbuttonclick;
diff --git a/ui/gtk/menu.c b/ui/gtk/menu.c
index a54a34b..521bf91 100644
--- a/ui/gtk/menu.c
+++ b/ui/gtk/menu.c
@@ -514,6 +514,7 @@ void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject
event->callback = i->callback;
event->value = 0;
event->customdata = NULL;
+ event->customint = 0;
g_signal_connect(
action,
@@ -613,6 +614,7 @@ void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject
event->userdata = il->userdata;
event->callback = il->callback;
event->customdata = var;
+ event->customint = 0;
event->value = 0;
g_signal_connect(
@@ -638,6 +640,7 @@ void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEvent
evt.window = event->obj->window;
evt.document = event->obj->ctx->document;
evt.eventdata = event->customdata;
+ evt.eventdatatype = event->customint;
evt.intval = intval;
event->callback(&evt, event->userdata);
}
@@ -652,6 +655,7 @@ void ui_menu_list_item_activate_event_wrapper(GSimpleAction* self, GVariant* par
evt.window = event->obj->window;
evt.document = event->obj->ctx->document;
evt.eventdata = ui_list_get(list, index);
+ evt.eventdatatype = UI_EVENT_DATA_LIST_ELM;
evt.intval = index;
event->callback(&evt, event->userdata);
diff --git a/ui/gtk/range.c b/ui/gtk/range.c
index c992159..45c5bfc 100644
--- a/ui/gtk/range.c
+++ b/ui/gtk/range.c
@@ -62,6 +62,7 @@ static UIWIDGET ui_scrollbar(UiObject *obj, UiOrientation orientation, UiRange *
event->callback = f;
event->value = 0;
event->customdata = NULL;
+ event->customint = 0;
g_signal_connect(
G_OBJECT(scrollbar),
@@ -76,7 +77,7 @@ static UIWIDGET ui_scrollbar(UiObject *obj, UiOrientation orientation, UiRange *
}
UiContainer *ct = uic_get_current_container(obj);
- ct->add(ct, scrollbar, FALSE);
+ ct->add(ct, scrollbar);
return scrollbar;
}
@@ -95,6 +96,7 @@ gboolean ui_scrollbar_value_changed(GtkRange *range, UiEventData *event) {
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = event->value;
event->callback(&e, event->userdata);
return TRUE;
diff --git a/ui/gtk/text.c b/ui/gtk/text.c
index 475543c..9ea0c4c 100644
--- a/ui/gtk/text.c
+++ b/ui/gtk/text.c
@@ -107,13 +107,13 @@ static GtkTextBuffer* create_textbuffer(UiTextArea *textarea) {
return buf;
}
-UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) {
+UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
UiObject* current = uic_current_obj(obj);
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_TEXT);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_TEXT);
GtkWidget *text_area = gtk_text_view_new();
- ui_set_name_and_style(text_area, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, text_area, args.groups);
+ ui_set_name_and_style(text_area, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, text_area, args->groups);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_area), GTK_WRAP_WORD_CHAR);
g_signal_connect(
@@ -127,8 +127,8 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) {
uitext->ctx = obj->ctx;
uitext->var = var;
uitext->last_selection_state = 0;
- uitext->onchange = args.onchange;
- uitext->onchangedata = args.onchangedata;
+ uitext->onchange = args->onchange;
+ uitext->onchangedata = args->onchangedata;
g_object_set_data(G_OBJECT(text_area), "ui_textarea", uitext);
@@ -155,8 +155,8 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) {
gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text_area), 2);
// add
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, scroll_area, TRUE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, scroll_area);
// bind value
if(var) {
@@ -330,6 +330,7 @@ void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea) {
e.window = e.obj->window;
e.document = textarea->ctx->document;
e.eventdata = value;
+ e.eventdatatype = UI_EVENT_DATA_TEXT_VALUE;
e.intval = 0;
e.set = ui_get_setop();
@@ -592,21 +593,21 @@ void ui_text_redo(UiText *value) {
-static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool password, UiTextFieldArgs args) {
+static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool password, UiTextFieldArgs *args) {
GtkWidget *textfield = gtk_entry_new();
- ui_set_name_and_style(textfield, args.name, args.style_class);
- ui_set_widget_groups(obj->ctx, textfield, args.groups);
+ ui_set_name_and_style(textfield, args->name, args->style_class);
+ ui_set_widget_groups(obj->ctx, textfield, args->groups);
UiObject* current = uic_current_obj(obj);
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING);
UiTextField *uitext = malloc(sizeof(UiTextField));
uitext->obj = obj;
uitext->var = var;
- uitext->onchange = args.onchange;
- uitext->onchangedata = args.onchangedata;
- uitext->onactivate = args.onactivate;
- uitext->onactivatedata = args.onactivatedata;
+ uitext->onchange = args->onchange;
+ uitext->onchangedata = args->onchangedata;
+ uitext->onactivate = args->onactivate;
+ uitext->onactivatedata = args->onactivatedata;
g_signal_connect(
textfield,
@@ -614,10 +615,10 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
G_CALLBACK(ui_textfield_destroy),
uitext);
- if(args.width > 0) {
+ if(args->width > 0) {
// TODO: gtk4
#if GTK_MAJOR_VERSION <= 3
- gtk_entry_set_width_chars(GTK_ENTRY(textfield), args.width);
+ gtk_entry_set_width_chars(GTK_ENTRY(textfield), args->width);
#endif
}
if(frameless) {
@@ -628,8 +629,8 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
gtk_entry_set_visibility(GTK_ENTRY(textfield), FALSE);
}
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, textfield, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, textfield);
if(var) {
UiString *value = var->value;
@@ -647,7 +648,7 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
value->obj = GTK_ENTRY(textfield);
}
- if(args.onchange || var) {
+ if(args->onchange || var) {
g_signal_connect(
textfield,
"changed",
@@ -655,7 +656,7 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
uitext);
}
- if(args.onactivate) {
+ if(args->onactivate) {
g_signal_connect(
textfield,
"activate",
@@ -666,15 +667,15 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
return textfield;
}
-UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args) {
+UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs *args) {
return create_textfield(obj, FALSE, FALSE, args);
}
-UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args) {
+UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *args) {
return create_textfield(obj, TRUE, FALSE, args);
}
-UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args) {
+UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args) {
return create_textfield(obj, FALSE, TRUE, args);
}
@@ -691,6 +692,7 @@ void ui_textfield_changed(GtkEditable *editable, UiTextField *textfield) {
e.window = e.obj->window;
e.document = textfield->obj->ctx->document;
e.eventdata = value;
+ e.eventdatatype = UI_EVENT_DATA_TEXT_VALUE;
e.intval = 0;
e.set = ui_get_setop();
@@ -710,6 +712,7 @@ void ui_textfield_activate(GtkEntry* self, UiTextField *textfield) {
e.window = e.obj->window;
e.document = textfield->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = 0;
e.set = ui_get_setop();
textfield->onactivate(&e, textfield->onactivatedata);
@@ -807,6 +810,7 @@ void ui_path_button_clicked(GtkWidget *widget, UiEventDataExt *event) {
evt.window = evt.obj->window;
evt.document = evt.obj->ctx->document;
evt.eventdata = elm->path;
+ evt.eventdatatype = UI_EVENT_DATA_STRING;
evt.intval = event->value0;
evt.set = ui_get_setop();
event->callback(&evt, event->userdata);
@@ -888,6 +892,7 @@ static void ui_path_textfield_activate(GtkWidget *entry, UiPathTextField *pathtf
evt.window = obj->window;
evt.document = obj->ctx->document;
evt.eventdata = (char*)text;
+ evt.eventdatatype = UI_EVENT_DATA_STRING;
evt.intval = -1;
pathtf->onactivate(&evt, pathtf->onactivatedata);
}
@@ -915,22 +920,22 @@ static gboolean ui_path_textfield_key_controller(
return FALSE;
}
-UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
+UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) {
UiObject* current = uic_current_obj(obj);
UiPathTextField *pathtf = malloc(sizeof(UiPathTextField));
memset(pathtf, 0, sizeof(UiPathTextField));
pathtf->obj = obj;
- pathtf->getpathelm = args.getpathelm;
- pathtf->getpathelmdata = args.getpathelmdata;
- pathtf->onactivate = args.onactivate;
- pathtf->onactivatedata = args.onactivatedata;
- pathtf->ondragcomplete = args.ondragcomplete;
- pathtf->ondragcompletedata = args.ondragcompletedata;
- pathtf->ondragstart = args.ondragstart;
- pathtf->ondragstartdata = args.ondragstartdata;
- pathtf->ondrop = args.ondrop;
- pathtf->ondropdata = args.ondropsdata;
+ pathtf->getpathelm = args->getpathelm;
+ pathtf->getpathelmdata = args->getpathelmdata;
+ pathtf->onactivate = args->onactivate;
+ pathtf->onactivatedata = args->onactivatedata;
+ pathtf->ondragcomplete = args->ondragcomplete;
+ pathtf->ondragcompletedata = args->ondragcompletedata;
+ pathtf->ondragstart = args->ondragstart;
+ pathtf->ondragstartdata = args->ondragstartdata;
+ pathtf->ondrop = args->ondrop;
+ pathtf->ondropdata = args->ondropsdata;
if(!pathtf->getpathelm) {
pathtf->getpathelm = default_pathelm_func;
@@ -940,8 +945,8 @@ UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
pathtf->stack = gtk_stack_new();
gtk_widget_set_name(pathtf->stack, "path-textfield-box");
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, pathtf->stack, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, pathtf->stack);
pathtf->entry_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
pathtf->entry = gtk_entry_new();
@@ -973,7 +978,7 @@ UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
gtk_stack_set_visible_child(GTK_STACK(pathtf->stack), pathtf->entry_box);
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING);
if (var) {
UiString* value = (UiString*)var->value;
value->obj = pathtf;
@@ -1076,22 +1081,22 @@ static GtkWidget* create_path_button_box() {
return bb;
}
-UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
+UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) {
UiObject* current = uic_current_obj(obj);
UiPathTextField *pathtf = malloc(sizeof(UiPathTextField));
memset(pathtf, 0, sizeof(UiPathTextField));
pathtf->obj = obj;
- pathtf->getpathelm = args.getpathelm;
- pathtf->getpathelmdata = args.getpathelmdata;
- pathtf->onactivate = args.onactivate;
- pathtf->onactivatedata = args.onactivatedata;
- pathtf->ondragcomplete = args.ondragcomplete;
- pathtf->ondragcompletedata = args.ondragcompletedata;
- pathtf->ondragstart = args.ondragstart;
- pathtf->ondragstartdata = args.ondragstartdata;
- pathtf->ondrop = args.ondrop;
- pathtf->ondropdata = args.ondropsdata;
+ pathtf->getpathelm = args->getpathelm;
+ pathtf->getpathelmdata = args->getpathelmdata;
+ pathtf->onactivate = args->onactivate;
+ pathtf->onactivatedata = args->onactivatedata;
+ pathtf->ondragcomplete = args->ondragcomplete;
+ pathtf->ondragcompletedata = args->ondragcompletedata;
+ pathtf->ondragstart = args->ondragstart;
+ pathtf->ondragstartdata = args->ondragstartdata;
+ pathtf->ondrop = args->ondrop;
+ pathtf->ondropdata = args->ondropsdata;
if(!pathtf->getpathelm) {
pathtf->getpathelm = default_pathelm_func;
@@ -1112,7 +1117,7 @@ UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
G_CALLBACK(ui_path_textfield_destroy),
pathtf);
- UI_APPLY_LAYOUT1(current, args);
+ UI_APPLY_LAYOUT2(current, args);
current->container->add(current->container, eventbox, FALSE);
// hbox as parent for the GtkEntry and GtkButtonBox
@@ -1137,7 +1142,7 @@ UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
G_CALLBACK(ui_path_textfield_key_press),
pathtf);
- UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING);
+ UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING);
if (var) {
UiString* value = (UiString*)var->value;
value->obj = pathtf;
diff --git a/ui/gtk/toolbar.c b/ui/gtk/toolbar.c
index 60c4bac..0409be9 100644
--- a/ui/gtk/toolbar.c
+++ b/ui/gtk/toolbar.c
@@ -155,6 +155,7 @@ void add_toolitem_widget(GtkToolbar *tb, UiToolbarItem *item, UiObject *obj) {
event->callback = item->args.onclick;
event->userdata = item->args.onclickdata;
event->customdata = NULL;
+ event->customint = 0;
event->value = 0;
g_signal_connect(
@@ -237,6 +238,7 @@ void ui_tool_button_toggled(GtkToggleToolButton *widget, UiVarEventData *event)
e.window = event->obj->window;
e.document = event->obj->ctx->document;
e.eventdata = NULL;
+ e.eventdatatype = 0;
e.intval = gtk_toggle_tool_button_get_active(widget);
if(event->callback) {
diff --git a/ui/gtk/toolkit.c b/ui/gtk/toolkit.c
index 7e8e3a5..7a26a70 100644
--- a/ui/gtk/toolkit.c
+++ b/ui/gtk/toolkit.c
@@ -191,6 +191,7 @@ static gboolean ui_job_finished(void *data) {
event.document = job->obj->ctx->document;
event.intval = 0;
event.eventdata = NULL;
+ event.eventdatatype = 0;
job->finish_callback(&event, job->finish_data);
free(job);
diff --git a/ui/gtk/toolkit.h b/ui/gtk/toolkit.h
index b98bb25..b66c695 100644
--- a/ui/gtk/toolkit.h
+++ b/ui/gtk/toolkit.h
@@ -131,6 +131,7 @@ typedef struct UiEventData {
ui_callback callback;
void *userdata;
int value;
+ int customint;
void *customdata;
} UiEventData;
diff --git a/ui/gtk/webview.c b/ui/gtk/webview.c
index 9f3bebb..3b9a946 100644
--- a/ui/gtk/webview.c
+++ b/ui/gtk/webview.c
@@ -33,14 +33,14 @@
#ifdef UI_WEBVIEW
-UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs args) {
+UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) {
UiObject* current = uic_current_obj(obj);
GtkWidget *webview = webkit_web_view_new();
- ui_set_name_and_style(webview, args.name, args.style_class);
+ ui_set_name_and_style(webview, args->name, args->style_class);
- UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_GENERIC);
+ UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_GENERIC);
if(var) {
WebViewData *data = malloc(sizeof(WebViewData));
memset(data, 0, sizeof(WebViewData));
@@ -59,9 +59,9 @@ UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs args) {
}
}
- ui_set_widget_groups(obj->ctx, webview, args.groups);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, webview, FALSE);
+ ui_set_widget_groups(obj->ctx, webview, args->groups);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, webview);
return webview;
}
@@ -115,7 +115,14 @@ void ui_webview_load_content(
const char *mimetype,
const char *encoding)
{
+ WebViewData *data0 = g->obj;
+ if(!data0) {
+ return;
+ }
+
WebViewData data;
+ memset(&data, 0, sizeof(WebViewData));
+ data.webview = data0->webview;
data.uri = (char*)uri;
data.content = (char*)content;
data.contentlength = contentlength;
diff --git a/ui/gtk/widget.c b/ui/gtk/widget.c
index 505bca6..36f4465 100644
--- a/ui/gtk/widget.c
+++ b/ui/gtk/widget.c
@@ -31,13 +31,13 @@
#include "../common/object.h"
-UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args) {
+UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args) {
UiObject* current = uic_current_obj(obj);
UIWIDGET widget = create_widget(obj, args, userdata);
- UI_APPLY_LAYOUT1(current, args);
- current->container->add(current->container, widget, FALSE);
+ UI_APPLY_LAYOUT2(current, args);
+ current->container->add(current->container, widget);
return widget;
}
@@ -47,7 +47,7 @@ UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args) {
GtkWidget *widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
ui_set_name_and_style(widget, args->name, args->style_class);
UI_APPLY_LAYOUT1(current, (*args));
- current->container->add(current->container, widget, FALSE);
+ current->container->add(current->container, widget);
return widget;
}
diff --git a/ui/gtk/window.c b/ui/gtk/window.c
index ca284c0..cdafae3 100644
--- a/ui/gtk/window.c
+++ b/ui/gtk/window.c
@@ -102,9 +102,7 @@ static gboolean close_request(GtkWidget* self, GdkEvent* event, UiObject *obj) {
#endif
static UiObject* create_window(const char *title, void *window_data, UiBool sidebar, UiBool simple) {
- CxMempool *mp = cxMempoolCreateSimple(256);
- UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject));
- obj->ref = 0;
+ UiObject *obj = uic_object_new_toplevel();
#ifdef UI_LIBADWAITA
obj->widget = adw_application_window_new(ui_get_application());
@@ -114,8 +112,6 @@ static UiObject* create_window(const char *title, void *window_data, UiBool side
obj->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
#endif
-
- obj->ctx = uic_context(obj, mp);
obj->window = window_data;
#if GTK_CHECK_VERSION(4, 0, 0)
@@ -316,6 +312,8 @@ static void dialog_response(AdwAlertDialog *self, gchar *response, UiEventData *
evt.document = evt.obj->ctx->document;
evt.window = evt.obj->window;
evt.eventdata = NULL;
+ evt.eventdatatype = 0;
+ evt.eventdatatype = 0;
evt.intval = 0;
if(!strcmp(response, "btn1")) {
@@ -327,6 +325,7 @@ static void dialog_response(AdwAlertDialog *self, gchar *response, UiEventData *
if(data->customdata) {
GtkWidget *entry = data->customdata;
evt.eventdata = (void*)ENTRY_GET_TEXT(GTK_ENTRY(entry));
+ evt.eventdatatype = UI_EVENT_DATA_STRING;
}
if(data->callback) {
@@ -340,6 +339,7 @@ void ui_dialog_create(UiObject *parent, UiDialogArgs args) {
event->callback = args.result;
event->userdata = args.resultdata;
event->customdata = NULL;
+ event->customint = 0;
event->value = 0;
event->obj = parent;
@@ -365,6 +365,7 @@ void ui_dialog_create(UiObject *parent, UiDialogArgs args) {
}
adw_alert_dialog_set_extra_child(ADW_ALERT_DIALOG(dialog), entry);
event->customdata = entry;
+ event->customint = 0;
}
g_signal_connect(
@@ -521,6 +522,7 @@ static void filechooser_opened(GObject *source, GAsyncResult *result, void *data
flist.files = NULL;
flist.nfiles = 0;
evt.eventdata = &flist;
+ evt.eventdatatype = UI_EVENT_DATA_FILE_LIST;
if(selection) {
flist = listmodel2filelist(selection);
@@ -555,6 +557,7 @@ static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsign
event->callback = file_selected_callback;
event->userdata = cbdata;
event->customdata = NULL;
+ event->customint = 0;
event->value = mode;
event->obj = obj;
@@ -761,9 +764,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs args) {
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
}
- CxMempool *mp = cxMempoolCreateSimple(256);
- UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject));
- obj->ctx = uic_context(obj, mp);
+ UiObject *obj = uic_object_new_toplevel();
obj->widget = dialog;
obj->ref = 0;
obj->destroy = ui_window_widget_destroy;
diff --git a/ui/ui/button.h b/ui/ui/button.h
index 7123858..fb578f7 100644
--- a/ui/ui/button.h
+++ b/ui/ui/button.h
@@ -36,7 +36,7 @@ extern "C" {
#endif
typedef struct UiButtonArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -58,7 +58,7 @@ typedef struct UiButtonArgs {
} UiButtonArgs;
typedef struct UiToggleArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -82,17 +82,17 @@ typedef struct UiToggleArgs {
const int* groups;
} UiToggleArgs;
-#define ui_button(obj, ...) ui_button_create(obj, (UiButtonArgs){ __VA_ARGS__ } )
-#define ui_togglebutton(obj, ...) ui_togglebutton_create(obj, (UiToggleArgs){ __VA_ARGS__ } )
-#define ui_checkbox(obj, ...) ui_checkbox_create(obj, (UiToggleArgs){ __VA_ARGS__ } )
-#define ui_switch(obj, ...) ui_switch_create(obj, (UiToggleArgs){ __VA_ARGS__ } )
-#define ui_radiobutton(obj, ...) ui_radiobutton_create(obj, (UiToggleArgs){ __VA_ARGS__ } )
+#define ui_button(obj, ...) ui_button_create(obj, &(UiButtonArgs){ __VA_ARGS__ } )
+#define ui_togglebutton(obj, ...) ui_togglebutton_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
+#define ui_checkbox(obj, ...) ui_checkbox_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
+#define ui_switch(obj, ...) ui_switch_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
+#define ui_radiobutton(obj, ...) ui_radiobutton_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
-UIEXPORT UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args);
-UIEXPORT UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args);
-UIEXPORT UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args);
-UIEXPORT UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args);
-UIEXPORT UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args);
+UIEXPORT UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args);
+UIEXPORT UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args);
+UIEXPORT UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args);
+UIEXPORT UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args);
+UIEXPORT UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs *args);
diff --git a/ui/ui/container.h b/ui/ui/container.h
index 3f828ea..75c78b0 100644
--- a/ui/ui/container.h
+++ b/ui/ui/container.h
@@ -59,7 +59,7 @@ typedef enum UiHeaderbarAlternative {
typedef struct UiContainerArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -81,7 +81,7 @@ typedef struct UiContainerArgs {
} UiContainerArgs;
typedef struct UiFrameArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -104,7 +104,7 @@ typedef struct UiFrameArgs {
} UiFrameArgs;
typedef struct UiTabViewArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -116,6 +116,8 @@ typedef struct UiTabViewArgs {
const char *style_class;
UiTabViewType tabview;
+ ui_callback onchange;
+ void *onchangedata;
UiSubContainerType subcontainer;
@@ -132,7 +134,7 @@ typedef struct UiTabViewArgs {
} UiTabViewArgs;
typedef struct UiHeaderbarArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -158,7 +160,7 @@ typedef struct UiSidebarArgs {
} UiSidebarArgs;
typedef struct UiSplitPaneArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -181,7 +183,7 @@ typedef struct UiSplitPaneArgs {
} UiSplitPaneArgs;
typedef struct UiItemListContainerArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -235,39 +237,39 @@ struct UiContainerX {
#define UI_CTN(obj, ctn) for(ctn;ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_vbox(obj, ...) for(ui_vbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_hbox(obj, ...) for(ui_hbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_grid(obj, ...) for(ui_grid_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_frame(obj, ...) for(ui_frame_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_expander(obj, ...) for(ui_expander_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_scrolledwindow(obj, ...) for(ui_scrolledwindow_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_tabview(obj, ...) for(ui_tabview_create(obj, (UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_headerbar(obj, ...) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_sidebar(obj, ...) for(ui_sidebar_create(obj, (UiSidebarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-
-#define ui_vbox0(obj) for(ui_vbox_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_hbox0(obj) for(ui_hbox_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_grid0(obj) for(ui_grid_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_frame0(obj) for(ui_frame_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_expander0(obj) for(ui_expande_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_scrolledwindow0(obj) for(ui_scrolledwindow_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_tabview0(obj) for(ui_tabview_create(obj, (UiTabViewArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_headerbar0(obj) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_sidebar0(obj) for(ui_sidebar_create(obj, (UiSidebarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-
-#define ui_vbox_w(obj, w, ...) for(w = ui_vbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_hbox_w(obj, w, ...) for(w = ui_hbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_grid_w(obj, w, ...) for(w = ui_grid_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_tabview_w(obj, w, ...) for(w = ui_tabview_create(obj, (UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_scrolledwindow_w(obj, w, ...) for(w = ui_scrolledwindow_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-
-#define ui_hsplitpane(obj, ...) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_vsplitpane(obj, ...) for(ui_vsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_hsplitpane0(obj) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_vsplitpane0(obj) for(ui_vsplitpane_create(obj, (UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
-
-#define ui_hsplitpane_w(obj, w, ...) for(w = ui_hsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
-#define ui_vsplitpane_w(obj, w, ...) for(w = ui_vsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_vbox(obj, ...) for(ui_vbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_hbox(obj, ...) for(ui_hbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_grid(obj, ...) for(ui_grid_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_frame(obj, ...) for(ui_frame_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_expander(obj, ...) for(ui_expander_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_scrolledwindow(obj, ...) for(ui_scrolledwindow_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_tabview(obj, ...) for(ui_tabview_create(obj, &(UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_headerbar(obj, ...) for(ui_headerbar_create(obj, &(UiHeaderbarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_sidebar(obj, ...) for(ui_sidebar_create(obj, &(UiSidebarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+
+#define ui_vbox0(obj) for(ui_vbox_create(obj, &(UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_hbox0(obj) for(ui_hbox_create(obj, &(UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_grid0(obj) for(ui_grid_create(obj, &(UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_frame0(obj) for(ui_frame_create(obj, &(UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_expander0(obj) for(ui_expande_create(obj, &(UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_scrolledwindow0(obj) for(ui_scrolledwindow_create(obj, &(UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_tabview0(obj) for(ui_tabview_create(obj, &(UiTabViewArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_headerbar0(obj) for(ui_headerbar_create(obj, &(UiHeaderbarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_sidebar0(obj) for(ui_sidebar_create(obj, &(UiSidebarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+
+#define ui_vbox_w(obj, w, ...) for(w = ui_vbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_hbox_w(obj, w, ...) for(w = ui_hbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_grid_w(obj, w, ...) for(w = ui_grid_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_tabview_w(obj, w, ...) for(w = ui_tabview_create(obj, &(UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_scrolledwindow_w(obj, w, ...) for(w = ui_scrolledwindow_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+
+#define ui_hsplitpane(obj, ...) for(ui_hsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_vsplitpane(obj, ...) for(ui_vsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_hsplitpane0(obj) for(ui_hsplitpane_create(obj, &(UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_vsplitpane0(obj) for(ui_vsplitpane_create(obj, &(UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+
+#define ui_hsplitpane_w(obj, w, ...) for(w = ui_hsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_vsplitpane_w(obj, w, ...) for(w = ui_vsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
#define ui_tab(obj, label) for(ui_tab_create(obj, label);ui_container_finish(obj);ui_container_begin_close(obj))
@@ -275,35 +277,35 @@ struct UiContainerX {
#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))
-#define ui_itemlist(obj, ...) ui_itemlist_create(obj, (UiItemListContainerArgs) { __VA_ARGS__} )
+#define ui_itemlist(obj, ...) ui_itemlist_create(obj, &(UiItemListContainerArgs) { __VA_ARGS__} )
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);
-UIEXPORT UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args);
-UIEXPORT UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs args);
-UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs args);
-UIEXPORT UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs args);
-
-UIEXPORT UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args);
+UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args);
+UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args);
+UIEXPORT UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args);
+UIEXPORT UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args);
+UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args);
+UIEXPORT UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs *args);
+
+UIEXPORT UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args);
UIEXPORT void ui_tab_create(UiObject *obj, const char* title);
UIEXPORT void ui_tabview_select(UIWIDGET tabview, int tab);
UIEXPORT void ui_tabview_remove(UIWIDGET tabview, int tab);
UIEXPORT UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index);
-UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args);
+UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args);
UIEXPORT void ui_headerbar_start_create(UiObject *obj);
UIEXPORT void ui_headerbar_center_create(UiObject *obj);
UIEXPORT void ui_headerbar_end_create(UiObject *obj);
-UIEXPORT UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args);
+UIEXPORT UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args);
-UIEXPORT UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args);
+UIEXPORT UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs *args);
-UIEXPORT UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args);
-UIEXPORT UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args);
+UIEXPORT UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs *args);
+UIEXPORT UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs *args);
UIEXPORT void ui_splitpane_set_visible(UIWIDGET splitpane, int child_index, UiBool visible);
@@ -342,6 +344,17 @@ UIEXPORT int ui_container_finish(UiObject *obj);
if(args.rowspan > 0) ui_layout_rowspan(obj, args.rowspan); \
/*force caller to add ';'*/(void)0
+#define UI_APPLY_LAYOUT2(obj, args) \
+ if(args->fill != UI_DEFAULT) ui_layout_fill(obj, args->fill == UI_ON ? 1 : 0 ); \
+ if(args->hexpand) ui_layout_hexpand(obj, 1); \
+ if(args->vexpand) ui_layout_vexpand(obj, 1); \
+ if(args->hfill) ui_layout_hfill(obj, 1); \
+ if(args->vfill) ui_layout_vfill(obj, 1); \
+ if(args->override_defaults) ui_layout_override_defaults(obj, 1); \
+ if(args->colspan > 0) ui_layout_colspan(obj, args->colspan); \
+ if(args->rowspan > 0) ui_layout_rowspan(obj, args->rowspan); \
+ /*force caller to add ';'*/(void)0
+
#ifdef __cplusplus
}
diff --git a/ui/ui/display.h b/ui/ui/display.h
index 8ed861b..3cb3d65 100644
--- a/ui/ui/display.h
+++ b/ui/ui/display.h
@@ -58,7 +58,7 @@ enum UiLabelStyle {
typedef enum UiLabelStyle UiLabelStyle;
typedef struct UiLabelArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -77,7 +77,7 @@ typedef struct UiLabelArgs {
} UiLabelArgs;
typedef struct UiProgressbarArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -96,7 +96,7 @@ typedef struct UiProgressbarArgs {
} UiProgressbarArgs;
typedef struct UiProgressbarSpinnerArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -113,24 +113,24 @@ typedef struct UiProgressbarSpinnerArgs {
/* label widgets */
-#define ui_label(obj, ...) ui_label_create(obj, (UiLabelArgs) { __VA_ARGS__ })
-#define ui_llabel(obj, ...) ui_llabel_create(obj, (UiLabelArgs) { __VA_ARGS__ })
-#define ui_rlabel(obj, ...) ui_rlabel_create(obj, (UiLabelArgs) { __VA_ARGS__ })
+#define ui_label(obj, ...) ui_label_create(obj, &(UiLabelArgs) { __VA_ARGS__ })
+#define ui_llabel(obj, ...) ui_llabel_create(obj, &(UiLabelArgs) { __VA_ARGS__ })
+#define ui_rlabel(obj, ...) ui_rlabel_create(obj, &(UiLabelArgs) { __VA_ARGS__ })
-UIEXPORT UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs args);
-UIEXPORT UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args);
-UIEXPORT UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args);
+UIEXPORT UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs *args);
+UIEXPORT UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs *args);
+UIEXPORT UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs *args);
UIWIDGET ui_space_deprecated(UiObject *obj);
/* progress bar/spinner */
-#define ui_progressbar(obj, ...) ui_progressbar_create(obj, (UiProgressbarArgs) { __VA_ARGS__ } )
-#define ui_progressspinner(obj, ...) ui_progressspinner_create(obj, (UiProgressbarSpinnerArgs) { __VA_ARGS__ } )
+#define ui_progressbar(obj, ...) ui_progressbar_create(obj, &(UiProgressbarArgs) { __VA_ARGS__ } )
+#define ui_progressspinner(obj, ...) ui_progressspinner_create(obj, &(UiProgressbarSpinnerArgs) { __VA_ARGS__ } )
-UIEXPORT UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args);
-UIEXPORT UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args);
+UIEXPORT UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs *args);
+UIEXPORT UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs *args);
#ifdef __cplusplus
diff --git a/ui/ui/entry.h b/ui/ui/entry.h
index 5c8990a..cb1b7f7 100644
--- a/ui/ui/entry.h
+++ b/ui/ui/entry.h
@@ -37,7 +37,7 @@ extern "C" {
typedef struct UiSpinnerArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -62,9 +62,9 @@ typedef struct UiSpinnerArgs {
-UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs args);
+UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs *args);
-#define ui_spinner(obj, ...) ui_spinner_create(obj, (UiSpinnerArgs){ __VA_ARGS__ } )
+#define ui_spinner(obj, ...) ui_spinner_create(obj, &(UiSpinnerArgs){ __VA_ARGS__ } )
void ui_spinner_setrange(UIWIDGET spinner, double min, double max);
void ui_spinner_setdigits(UIWIDGET spinner, int digits);
diff --git a/ui/ui/icons.h b/ui/ui/icons.h
index cd4ef6c..9bc86a4 100644
--- a/ui/ui/icons.h
+++ b/ui/ui/icons.h
@@ -49,6 +49,8 @@ extern "C" {
#define UI_ICON_DOCK_RIGHT ""
#define UI_ICON_GO_BACK "go-previous"
#define UI_ICON_GO_FORWARD "go-next"
+#define UI_ICON_GO_UP "go-up"
+#define UI_ICON_GO_DOWN "go-down"
#endif /* UI_GTK */
@@ -68,6 +70,8 @@ extern "C" {
#define UI_ICON_DOCK_RIGHT "DockRight"
#define UI_ICON_GO_BACK "Back"
#define UI_ICON_GO_FORWARD "Forward"
+#define UI_ICON_GO_UP "Up"
+#define UI_ICON_GO_DOWN "" // TODO: implement workaround for missing down symbol
#endif /* UI_WINUI */
diff --git a/ui/ui/image.h b/ui/ui/image.h
index 7217caa..405b509 100644
--- a/ui/ui/image.h
+++ b/ui/ui/image.h
@@ -45,7 +45,7 @@ extern "C" {
typedef struct UiImageViewerArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -75,9 +75,9 @@ typedef struct UiImageViewerArgs {
void *onbuttonreleasedata;
} UiImageViewerArgs;
-#define ui_imageviewer(obj, ...) ui_imageviewer_create(obj, (UiImageViewerArgs){ __VA_ARGS__ } )
+#define ui_imageviewer(obj, ...) ui_imageviewer_create(obj, &(UiImageViewerArgs){ __VA_ARGS__ } )
-UIEXPORT UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args);
+UIEXPORT UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs *args);
UIEXPORT UIWIDGET ui_imageviewer_reset(UIWIDGET w);
UIEXPORT UIWIDGET ui_imageviewer_set_autoscale(UIWIDGET w, UiBool set);
diff --git a/ui/ui/menu.h b/ui/ui/menu.h
index 2e7b6b1..3f805b8 100644
--- a/ui/ui/menu.h
+++ b/ui/ui/menu.h
@@ -69,23 +69,23 @@ typedef struct UiMenuItemListArgs {
#define ui_menu(label) for(ui_menu_create(label);ui_menu_is_open();ui_menu_close())
-#define ui_menuitem(...) ui_menuitem_create((UiMenuItemArgs){ __VA_ARGS__ })
-#define ui_menu_toggleitem(...) ui_menu_toggleitem_create((UiMenuToggleItemArgs){ __VA_ARGS__ })
-#define ui_menu_radioitem(...) ui_menu_radioitem_create((UiMenuToggleItemArgs){ __VA_ARGS__ })
-#define ui_menu_itemlist(...) ui_menu_itemlist_create((UiMenuItemListArgs) { __VA_ARGS__ } )
-#define ui_menu_togglelist(...) ui_menu_itemlist_create((UiMenuItemListArgs) { __VA_ARGS} )
-#define ui_menu_radiolist(...) ui_menu_itemlist_create((UiMenuItemListArgs) { __VA_ARGS} )
+#define ui_menuitem(...) ui_menuitem_create(&(UiMenuItemArgs){ __VA_ARGS__ })
+#define ui_menu_toggleitem(...) ui_menu_toggleitem_create(&(UiMenuToggleItemArgs){ __VA_ARGS__ })
+#define ui_menu_radioitem(...) ui_menu_radioitem_create(&(UiMenuToggleItemArgs){ __VA_ARGS__ })
+#define ui_menu_itemlist(...) ui_menu_itemlist_create(&(UiMenuItemListArgs) { __VA_ARGS__ } )
+#define ui_menu_togglelist(...) ui_menu_itemlist_create(&(UiMenuItemListArgs) { __VA_ARGS} )
+#define ui_menu_radiolist(...) ui_menu_itemlist_create(&(UiMenuItemListArgs) { __VA_ARGS} )
UIEXPORT void ui_menu_create(const char* label);
-UIEXPORT void ui_menuitem_create(UiMenuItemArgs args);
-UIEXPORT void ui_menu_toggleitem_create(UiMenuToggleItemArgs args);
-UIEXPORT void ui_menu_radioitem_create(UiMenuToggleItemArgs args);
+UIEXPORT void ui_menuitem_create(UiMenuItemArgs *args);
+UIEXPORT void ui_menu_toggleitem_create(UiMenuToggleItemArgs *args);
+UIEXPORT void ui_menu_radioitem_create(UiMenuToggleItemArgs *args);
UIEXPORT void ui_menuseparator();
-UIEXPORT void ui_menu_itemlist_create(UiMenuItemListArgs args);
-UIEXPORT void ui_menu_toggleitemlist_create(UiMenuItemListArgs args);
-UIEXPORT void ui_menu_radioitemlist_create(UiMenuItemListArgs args);
+UIEXPORT void ui_menu_itemlist_create(UiMenuItemListArgs *args);
+UIEXPORT void ui_menu_toggleitemlist_create(UiMenuItemListArgs *args);
+UIEXPORT void ui_menu_radioitemlist_create(UiMenuItemListArgs *args);
UIEXPORT void ui_menu_end(void); // TODO: private
diff --git a/ui/ui/text.h b/ui/ui/text.h
index 5c40df5..0daf925 100644
--- a/ui/ui/text.h
+++ b/ui/ui/text.h
@@ -36,7 +36,7 @@ extern "C" {
#endif
typedef struct UiTextAreaArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -57,7 +57,7 @@ typedef struct UiTextAreaArgs {
} UiTextAreaArgs;
typedef struct UiTextFieldArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -91,7 +91,7 @@ typedef UiPathElm*(*ui_pathelm_func)(const char *full_path, size_t len, size_t *
typedef struct UiPathTextFieldArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -119,25 +119,25 @@ typedef struct UiPathTextFieldArgs {
void *ondropsdata;
} UiPathTextFieldArgs;
-#define ui_textarea(obj, ...) ui_textarea_create(obj, (UiTextAreaArgs) { __VA_ARGS__ })
+#define ui_textarea(obj, ...) ui_textarea_create(obj, &(UiTextAreaArgs) { __VA_ARGS__ })
-UIEXPORT UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args);
+UIEXPORT UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args);
UIEXPORT UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea);
UIEXPORT void ui_text_undo(UiText *value);
UIEXPORT void ui_text_redo(UiText *value);
-#define ui_textfield(obj, ...) ui_textfield_create(obj, (UiTextFieldArgs) { __VA_ARGS__ })
-#define ui_frameless_textfield(obj, ...) ui_frameless_field_create(obj, (UiTextFieldArgs) { __VA_ARGS__ })
-#define ui_passwordfield(obj, ...) ui_passwordfield_create(obj, (UiTextFieldArgs) { __VA_ARGS__ })
-#define ui_path_textfield(obj, ...) ui_path_textfield_create(obj, (UiPathTextFieldArgs) { __VA_ARGS__ } )
+#define ui_textfield(obj, ...) ui_textfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
+#define ui_frameless_textfield(obj, ...) ui_frameless_field_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
+#define ui_passwordfield(obj, ...) ui_passwordfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
+#define ui_path_textfield(obj, ...) ui_path_textfield_create(obj, &(UiPathTextFieldArgs) { __VA_ARGS__ } )
-UIEXPORT UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args);
-UIEXPORT UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args);
-UIEXPORT UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args);
+UIEXPORT UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs *args);
+UIEXPORT UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *args);
+UIEXPORT UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args);
-UIEXPORT UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args);
+UIEXPORT UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args);
#ifdef __cplusplus
}
diff --git a/ui/ui/toolbar.h b/ui/ui/toolbar.h
index 0509321..4b42af2 100644
--- a/ui/ui/toolbar.h
+++ b/ui/ui/toolbar.h
@@ -71,16 +71,16 @@ enum UiToolbarPos {
UI_TOOLBAR_RIGHT
};
-#define ui_toolbar_item(name, ...) ui_toolbar_item_create(name, (UiToolbarItemArgs){ __VA_ARGS__ } )
-#define ui_toolbar_toggleitem(name, ...) ui_toolbar_toggleitem_create(name, (UiToolbarToggleItemArgs){ __VA_ARGS__ } )
+#define ui_toolbar_item(name, ...) ui_toolbar_item_create(name, &(UiToolbarItemArgs){ __VA_ARGS__ } )
+#define ui_toolbar_toggleitem(name, ...) ui_toolbar_toggleitem_create(name, &(UiToolbarToggleItemArgs){ __VA_ARGS__ } )
-#define ui_toolbar_menu(name, ...) for(ui_toolbar_menu_create(name, (UiToolbarMenuArgs){ __VA_ARGS__ });ui_menu_is_open();ui_menu_close())
-#define ui_toolbar_appmenu() for(ui_toolbar_menu_create(NULL, (UiToolbarMenuArgs){ 0 });ui_menu_is_open();ui_menu_close())
+#define ui_toolbar_menu(name, ...) for(ui_toolbar_menu_create(name, &(UiToolbarMenuArgs){ __VA_ARGS__ });ui_menu_is_open();ui_menu_close())
+#define ui_toolbar_appmenu() for(ui_toolbar_menu_create(NULL, &(UiToolbarMenuArgs){ 0 });ui_menu_is_open();ui_menu_close())
-UIEXPORT void ui_toolbar_item_create(const char* name, UiToolbarItemArgs args);
-UIEXPORT void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs args);
-UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs args);
+UIEXPORT void ui_toolbar_item_create(const char* name, UiToolbarItemArgs *args);
+UIEXPORT void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs *args);
+UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs *args);
UIEXPORT void ui_toolbar_add_default(const char *name, enum UiToolbarPos pos);
diff --git a/ui/ui/toolkit.h b/ui/ui/toolkit.h
index 2af07c5..7b54742 100644
--- a/ui/ui/toolkit.h
+++ b/ui/ui/toolkit.h
@@ -92,7 +92,11 @@ typedef void* UIMENU; // NSMenu*
#define UIEXPORT __declspec(dllexport)
-#define UIWIDGET void*
+typedef struct W32Widget {
+ HWND hwnd;
+} W32Widget;
+
+#define UIWIDGET W32Widget*
#define UIWINDOW void*
#define UIMENU void*
@@ -217,7 +221,6 @@ typedef enum UiTri {
UI_OFF
} UiTri;
-
enum UiMouseEventType { UI_PRESS = 0, UI_PRESS2 };
typedef enum UiLabelType {
@@ -237,7 +240,8 @@ typedef enum UiDnDAction {
typedef void(*ui_callback)(UiEvent*, void*); /* event, user data */
-typedef void*(*ui_getvaluefunc)(void*, int);
+typedef void*(*ui_getvaluefunc)(void *elm, int col);
+typedef void*(*ui_getvaluefunc2)(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult);
typedef int(*ui_threadfunc)(void*);
@@ -318,6 +322,7 @@ struct UiEvent {
void *document;
void *window;
void *eventdata;
+ int eventdatatype;
int intval;
int set;
};
@@ -405,6 +410,8 @@ struct UiGeneric {
UiObserver *observers;
};
+typedef void (*ui_list_init_func)(UiContext *ctx, UiList *list, void *userdata);
+
/*
* abstract list
*/
@@ -470,6 +477,22 @@ typedef struct UiCondVar {
int intdata;
} UiCondVar;
+enum UiEventType {
+ UI_EVENT_DATA_NULL = 0,
+ UI_EVENT_DATA_POINTER,
+ UI_EVENT_DATA_STRING,
+ UI_EVENT_DATA_INTEGER_VALUE,
+ UI_EVENT_DATA_STRING_VALUE,
+ UI_EVENT_DATA_TEXT_VALUE,
+ UI_EVENT_DATA_DOUBLE_VALUE,
+ UI_EVENT_DATA_RANGE_VALUE,
+ UI_EVENT_DATA_LIST_SELECTION,
+ UI_EVENT_DATA_LIST_ELM,
+ UI_EVENT_DATA_DND,
+ UI_EVENT_DATA_SUBLIST,
+ UI_EVENT_DATA_FILE_LIST
+};
+
UIEXPORT void ui_init(const char *appname, int argc, char **argv);
UIEXPORT const char* ui_appname();
@@ -482,6 +505,8 @@ UIEXPORT void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata)
UIEXPORT void ui_context_destroy(UiContext *ctx);
+UIEXPORT UiContext* ui_context_parent(UiContext *ctx);
+
UIEXPORT void ui_object_ref(UiObject *obj);
UIEXPORT int ui_object_unref(UiObject *obj);
@@ -502,17 +527,12 @@ UIEXPORT void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc
UIEXPORT void* ui_document_new(size_t size);
UIEXPORT void ui_document_destroy(void *doc);
-UIEXPORT void ui_set_document(UiObject *obj, void *document); // deprecated
-UIEXPORT void ui_detach_document(UiObject *obj); // deprecated
-UIEXPORT void* ui_get_document(UiObject *obj); // deprecated
-UIEXPORT void ui_set_subdocument(void *document, void *sub); // deprecated
-UIEXPORT void ui_detach_subdocument(void *document, void *sub); // deprecated
UIEXPORT void* ui_get_subdocument(void *document); // deprecated
UIEXPORT UiContext* ui_document_context(void *doc);
UIEXPORT void ui_attach_document(UiContext *ctx, void *document);
-UIEXPORT void ui_detach_document2(UiContext *ctx, void *document);
+UIEXPORT void ui_detach_document(UiContext *ctx, void *document);
UIEXPORT void ui_widget_set_groups(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...);
@@ -531,12 +551,12 @@ UIEXPORT char* ui_strdup(UiContext *ctx, const char *str);
// types
-UIEXPORT UiInteger* ui_int_new(UiContext *ctx, char *name);
-UIEXPORT UiDouble* ui_double_new(UiContext *ctx, char *name);
-UIEXPORT UiString* ui_string_new(UiContext *ctx, char *name);
-UIEXPORT UiText* ui_text_new(UiContext *ctx, char *name);
-UIEXPORT UiRange* ui_range_new(UiContext *ctx, char *name);
-UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, char *name);
+UIEXPORT UiInteger* ui_int_new(UiContext *ctx, const char *name);
+UIEXPORT UiDouble* ui_double_new(UiContext *ctx, const char *name);
+UIEXPORT UiString* ui_string_new(UiContext *ctx, const char *name);
+UIEXPORT UiText* ui_text_new(UiContext *ctx, const char *name);
+UIEXPORT UiRange* ui_range_new(UiContext *ctx, const char *name);
+UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, const char *name);
#define ui_get(v) _Generic(v, \
UiInteger*: ui_int_get, \
@@ -558,6 +578,8 @@ UIEXPORT void ui_string_set(UiString *s, const char *value);
UIEXPORT char* ui_string_get(UiString *s);
UIEXPORT void ui_text_set(UiText *s, const char* value);
UIEXPORT char* ui_text_get(UiText *s);
+UIEXPORT void ui_generic_set_image(UiGeneric *g, void *img);
+UIEXPORT void* ui_generic_get_image(UiGeneric *g);
UIEXPORT void ui_var_set_int(UiContext *ctx, const char *name, int64_t value);
UIEXPORT int64_t ui_var_get_int(UiContext *ctx, const char *name);
@@ -574,7 +596,8 @@ UIEXPORT void ui_notify_except(UiObserver *observer, UiObserver *exc, void *data
UIEXPORT void ui_notify_evt(UiObserver *observer, UiEvent *event);
-UIEXPORT UiList* ui_list_new(UiContext *ctx, char *name);
+UIEXPORT UiList* ui_list_new(UiContext *ctx, const char *name);
+UIEXPORT UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func init, void *userdata);
UIEXPORT void ui_list_free(UiList *list);
UIEXPORT void* ui_list_first(UiList *list);
UIEXPORT void* ui_list_next(UiList *list);
@@ -624,6 +647,15 @@ UIEXPORT void ui_condvar_destroy(UiCondVar *var);
UIEXPORT void ui_setop_enable(int set);
UIEXPORT int ui_get_setop(void);
+
+UIEXPORT void ui_global_list_initializer(ui_list_init_func func, void *userdata);
+UIEXPORT void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list));
+UIEXPORT void ui_list_class_set_next(UiList *list, void*(*next)(UiList *list));
+UIEXPORT void ui_list_class_set_get(UiList *list, void*(*get)(UiList *list, int i));
+UIEXPORT void ui_list_class_set_count(UiList *list, int(*count)(UiList *list));
+UIEXPORT void ui_list_class_set_data(UiList *list, void *data);
+UIEXPORT void ui_list_class_set_iter(UiList *list, void *iter);
+
#ifdef __cplusplus
}
#endif
diff --git a/ui/ui/tree.h b/ui/ui/tree.h
index 8217cf6..af51d08 100644
--- a/ui/ui/tree.h
+++ b/ui/ui/tree.h
@@ -78,12 +78,23 @@ struct UiModel {
int *columnsize;
/*
+ * void*(*ui_getvaluefunc)(void *elm, int col);
+ *
* function for translating model data to view data
- * first argument is the pointer returned by UiList->get or UiTree->get
+ * first argument is the pointer returned by UiList first|next|get
* second argument is the column index
* TODO: return
*/
- void*(*getvalue)(void*, int);
+ ui_getvaluefunc getvalue;
+
+ /*
+ * void*(*ui_getvaluefunc2)(UiList *list, void *elm, int row, int col, void *userdata)
+ *
+ * alternative for getvalue
+ */
+ ui_getvaluefunc2 getvalue2;
+
+ void *getvalue2data;
};
struct UiListCallbacks {
@@ -104,7 +115,7 @@ struct UiListCallbacks {
};
struct UiListArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -121,6 +132,8 @@ struct UiListArgs {
char **static_elements;
size_t static_nelm;
ui_getvaluefunc getvalue;
+ ui_getvaluefunc2 getvalue2;
+ void *getvalue2data;
ui_callback onactivate;
void* onactivatedata;
ui_callback onselection;
@@ -130,14 +143,14 @@ struct UiListArgs {
ui_callback ondragcomplete;
void* ondragcompletedata;
ui_callback ondrop;
- void* ondropsdata;
+ void* ondropdata;
UiBool multiselection;
UiMenuBuilder *contextmenu;
const int *groups;
};
-typedef void (*ui_sublist_getvalue_func)(void *sublist_userdata, void *rowdata, int index, UiSubListItem *item);
+typedef void (*ui_sublist_getvalue_func)(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata);
struct UiSubList {
UiList *value;
@@ -171,7 +184,7 @@ struct UiSubListItem {
};
struct UiSourceListArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -219,6 +232,11 @@ struct UiSourceListArgs {
*/
ui_sublist_getvalue_func getvalue;
+ /*
+ * getvalue_func userdata
+ */
+ void *getvaluedata;
+
/*
* activated when a list item is selected
*/
@@ -240,21 +258,28 @@ UIEXPORT UiModel* ui_model(UiContext *ctx, ...);
UIEXPORT UiModel* ui_model_copy(UiContext *ctx, UiModel* model);
UIEXPORT void ui_model_free(UiContext *ctx, UiModel *mi);
-#define ui_listview(obj, ...) ui_listview_create(obj, (UiListArgs) { __VA_ARGS__ } )
-#define ui_table(obj, ...) ui_table_create(obj, (UiListArgs) { __VA_ARGS__ } )
-#define ui_combobox(obj, ...) ui_combobox_create(obj, (UiListArgs) { __VA_ARGS__ } )
-#define ui_breadcrumbbar(obj, ...) ui_breadcrumbbar_create(obj, (UiListArgs) { __VA_ARGS__ } )
-#define ui_sourcelist(obj, ...) ui_sourcelist_create(obj, (UiSourceListArgs) { __VA_ARGS__ } )
+#define ui_listview(obj, ...) ui_listview_create(obj, &(UiListArgs) { __VA_ARGS__ } )
+#define ui_table(obj, ...) ui_table_create(obj, &(UiListArgs) { __VA_ARGS__ } )
+#define ui_combobox(obj, ...) ui_combobox_create(obj, &(UiListArgs) { __VA_ARGS__ } )
+#define ui_breadcrumbbar(obj, ...) ui_breadcrumbbar_create(obj, &(UiListArgs) { __VA_ARGS__ } )
+#define ui_sourcelist(obj, ...) ui_sourcelist_create(obj, &(UiSourceListArgs) { __VA_ARGS__ } )
-UIEXPORT UIWIDGET ui_listview_create(UiObject* obj, UiListArgs args);
-UIEXPORT UIWIDGET ui_table_create(UiObject* obj, UiListArgs args);
-UIEXPORT UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs args);
-UIEXPORT UIWIDGET ui_breadcrumbbar_create(UiObject* obj, UiListArgs args);
+UIEXPORT UIWIDGET ui_listview_create(UiObject* obj, UiListArgs *args);
+UIEXPORT UIWIDGET ui_table_create(UiObject* obj, UiListArgs *args);
+UIEXPORT UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs *args);
+UIEXPORT UIWIDGET ui_breadcrumbbar_create(UiObject* obj, UiListArgs *args);
UIEXPORT void ui_listview_select(UIWIDGET listview, int index);
UIEXPORT void ui_combobox_select(UIWIDGET dropdown, int index);
-UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args);
+UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args);
+
+UIEXPORT void ui_sublist_item_set_icon(UiSubListItem *item, const char *icon);
+UIEXPORT void ui_sublist_item_set_label(UiSubListItem *item, const char *label);
+UIEXPORT void ui_sublist_item_set_button_icon(UiSubListItem *item, const char *button_icon);
+UIEXPORT void ui_sublist_item_set_button_label(UiSubListItem *item, const char *button_label);
+UIEXPORT void ui_sublist_item_set_badge(UiSubListItem *item, const char *badge);
+UIEXPORT void ui_sublist_item_set_eventdata(UiSubListItem *item, void *eventdata);
#ifdef __cplusplus
diff --git a/ui/ui/webview.h b/ui/ui/webview.h
index 98be28c..36f77f9 100644
--- a/ui/ui/webview.h
+++ b/ui/ui/webview.h
@@ -56,9 +56,9 @@ typedef struct UiWebviewArgs {
const int* groups;
} UiWebviewArgs;
-#define ui_webview(obj, ...) ui_webview_create(obj, (UiWebviewArgs){ __VA_ARGS__ } )
+#define ui_webview(obj, ...) ui_webview_create(obj, &(UiWebviewArgs){ __VA_ARGS__ } )
-UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs args);
+UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args);
void ui_webview_load_url(UiGeneric *g, const char *url);
diff --git a/ui/ui/widget.h b/ui/ui/widget.h
index e08233d..fee08d9 100644
--- a/ui/ui/widget.h
+++ b/ui/ui/widget.h
@@ -35,7 +35,7 @@ extern "C" {
#endif
typedef struct UiWidgetArgs {
- UiTri fill;
+ UiBool fill;
UiBool hexpand;
UiBool vexpand;
UiBool hfill;
@@ -48,21 +48,21 @@ typedef struct UiWidgetArgs {
} UiWidgetArgs;
#ifdef UI_GTK
-typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata);
+typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
#elif defined(UI_QT)
-typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata);
+typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
#elif defined(UI_MOTIF)
-typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata, Widget parent, Arg *a, int n);
+typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata, Widget parent, Arg *a, int n);
#elif defined(UI_COCOA)
-typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata);
+typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
#elif defined(UI_WINUI)
-typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata);
+typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
#elif defined(UI_WIN32)
-typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata);
+typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
#endif
-UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args);
+UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args);
-#define ui_customwidget(obj, create_widget, userdata, ...) ui_customwidget_create(obj, create_widget, userdata, (UiWidgetArgs) { __VA_ARGS__ })
+#define ui_customwidget(obj, create_widget, userdata, ...) ui_customwidget_create(obj, create_widget, userdata, &(UiWidgetArgs) { __VA_ARGS__ })
UIEXPORT UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args);
--
2.47.3