# HG changeset patch # User Olaf Wintermann # Date 1764533520 -3600 # Node ID cc23aad6335e5a30d1f26fcea4e87b0295fc52d6 # Parent 9b5948aa5b906238aca7f2e33c2280ccd636c482 move message handler to ui common diff -r 9b5948aa5b90 -r cc23aad6335e client/Makefile --- a/client/Makefile Sun Nov 30 18:17:49 2025 +0100 +++ b/client/Makefile Sun Nov 30 21:12:00 2025 +0100 @@ -32,7 +32,6 @@ CFLAGS += -I../ui/ -I../ucx APP_BIN_OBJ = ../build/client/main$(OBJ_EXT) -APP_BIN_OBJ += ../build/client/message$(OBJ_EXT) APP_BIN_OBJ += ../build/client/uiclient$(OBJ_EXT) APP_BIN_OBJ += ../build/client/args$(OBJ_EXT) diff -r 9b5948aa5b90 -r cc23aad6335e client/main.c --- a/client/main.c Sun Nov 30 18:17:49 2025 +0100 +++ b/client/main.c Sun Nov 30 21:12:00 2025 +0100 @@ -86,7 +86,7 @@ return 1; } } - MessageHandler *h = simple_msg_handler(in, out, client_msg_received); + UiMessageHandler *h = uic_simple_msg_handler(in, out, client_msg_received); client_init(h); h->start(h); diff -r 9b5948aa5b90 -r cc23aad6335e client/main.h --- a/client/main.h Sun Nov 30 18:17:49 2025 +0100 +++ b/client/main.h Sun Nov 30 21:12:00 2025 +0100 @@ -31,7 +31,7 @@ #include -#include "message.h" +#include "../ui/common/message.h" #ifdef __cplusplus extern "C" { diff -r 9b5948aa5b90 -r cc23aad6335e client/message.c --- a/client/message.c Sun Nov 30 18:17:49 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -/* - * 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 -#include -#include - -#include "message.h" - -MessageHandler* simple_msg_handler(int in, int out, msg_received_callback callback) { - SimpleMessageHandler *handler = malloc(sizeof(SimpleMessageHandler)); - handler->handler.start = simple_msg_handler_start; - handler->handler.stop = simple_msg_handler_stop; - handler->handler.send = simple_msg_handler_send; - handler->handler.callback = callback; - handler->in = in; - handler->out = out; - handler->outbuf = cxBufferCreate(NULL, 4096, NULL, CX_BUFFER_FREE_CONTENTS | CX_BUFFER_AUTO_EXTEND); - handler->stop = 0; - pthread_mutex_init(&handler->queue_lock, NULL); - pthread_mutex_init(&handler->avlbl_lock, NULL); - pthread_cond_init(&handler->available, NULL); - return (MessageHandler*)handler; -} - -int simple_msg_handler_start(MessageHandler *handler) { - SimpleMessageHandler *sh = (SimpleMessageHandler*)handler; - if(pthread_create(&sh->in_thread, NULL, simple_msg_handler_in_thread, sh)) { - return 1; - } - if(pthread_create(&sh->out_thread, NULL, simple_msg_handler_out_thread, sh)) { - return 1; - } - return 0; -} - -int simple_msg_handler_stop(MessageHandler *handler) { - SimpleMessageHandler *sh = (SimpleMessageHandler*)handler; - pthread_mutex_lock(&sh->queue_lock); - sh->stop = 0; - pthread_cond_signal(&sh->available); - pthread_mutex_unlock(&sh->queue_lock); - close(sh->in); - sh->in = -1; - - pthread_join(sh->in_thread, NULL); - pthread_join(sh->out_thread, NULL); - - return 0; -} - -int simple_msg_handler_send(MessageHandler *handler, cxstring msg) { - SimpleMessageHandler *sh = (SimpleMessageHandler*)handler; - pthread_mutex_lock(&sh->queue_lock); - cxBufferWrite(msg.ptr, 1, msg.length, sh->outbuf); - pthread_cond_signal(&sh->available); - pthread_mutex_unlock(&sh->queue_lock); - return 0; -} - -#define HEADERBUF_SIZE 64 - -void* simple_msg_handler_in_thread(void *data) { - SimpleMessageHandler *handler = data; - - char *msg = NULL; - size_t msg_size = 0; - size_t msg_pos = 0; // currently received message length - - char headerbuf[HEADERBUF_SIZE]; - size_t headerpos = 0; - - char buf[2048]; - ssize_t r; - while((r = read(handler->in, buf, 2024)) > 0) { - char *buffer = buf; - size_t available = r; - - while(available > 0) { - if(msg) { - // read message - size_t need = msg_size - msg_pos; - size_t cplen = r > need ? need : available; - memcpy(msg+msg_pos, buffer, cplen); - buffer += cplen; - available -= cplen; - msg_pos += cplen; - if(msg_pos == msg_size) { - // message complete - //fprintf(stderr, "send: %.*s\n", (int)msg_size, msg); - if(handler->handler.callback) { - handler->handler.callback(cx_mutstrn(msg, msg_size)); - } - msg = NULL; - msg_size = 0; - msg_pos = 0; - } - } else { - size_t header_max = HEADERBUF_SIZE - headerpos - 1; - if(header_max > available) { - header_max = available; - } - // search for line break - int i; - int header_complete = 0; - for(i=0;i= HEADERBUF_SIZE) { - fprintf(stderr, "Error: message header too big\n"); - exit(-1); - } - } - } - - - } - perror("error"); - fprintf(stderr, "stop simple_msg_handler_in_thread\n"); - - return NULL; -} - -void* simple_msg_handler_out_thread(void *data) { - SimpleMessageHandler *handler = data; - - return NULL; -} diff -r 9b5948aa5b90 -r cc23aad6335e client/message.h --- a/client/message.h Sun Nov 30 18:17:49 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * 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 CLIENT_MESSAGE_H -#define CLIENT_MESSAGE_H - -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct MessageHandler MessageHandler; - -typedef void(*msg_received_callback)(cxmutstr msg); - -struct MessageHandler { - int (*start)(MessageHandler *handler); - int (*stop)(MessageHandler *handler); - int (*send)(MessageHandler *handler, cxstring msg); - - msg_received_callback callback; -}; - -typedef struct SimpleMessageHandler { - MessageHandler handler; - int in; - int out; - pthread_t in_thread; - pthread_t out_thread; - pthread_mutex_t queue_lock; - pthread_mutex_t avlbl_lock; - pthread_cond_t available; - CxBuffer *outbuf; - int stop; -} SimpleMessageHandler; - -MessageHandler* simple_msg_handler(int in, int out, msg_received_callback callback); -int simple_msg_handler_start(MessageHandler *handler); -int simple_msg_handler_stop(MessageHandler *handler); -int simple_msg_handler_send(MessageHandler *handler, cxstring msg); - -void* simple_msg_handler_in_thread(void *data); -void* simple_msg_handler_out_thread(void *data); - - -#ifdef __cplusplus -} -#endif - -#endif /* CLIENT_MESSAGE_H */ - diff -r 9b5948aa5b90 -r cc23aad6335e client/uiclient.c --- a/client/uiclient.c Sun Nov 30 18:17:49 2025 +0100 +++ b/client/uiclient.c Sun Nov 30 21:12:00 2025 +0100 @@ -33,12 +33,12 @@ #include "../ui/common/args.h" -static MessageHandler *io; +static UiMessageHandler *io; static CxMap *msg_types; static CxMap *objects; -void client_init(MessageHandler *handler) { +void client_init(UiMessageHandler *handler) { io = handler; msg_types = cxHashMapCreateSimple(CX_STORE_POINTERS); diff -r 9b5948aa5b90 -r cc23aad6335e client/uiclient.h --- a/client/uiclient.h Sun Nov 30 18:17:49 2025 +0100 +++ b/client/uiclient.h Sun Nov 30 21:12:00 2025 +0100 @@ -34,7 +34,7 @@ #include #include -#include "message.h" +#include "../ui/common/message.h" #ifdef __cplusplus extern "C" { @@ -46,7 +46,7 @@ typedef int (*json_msg_handler)(UiObject *parent, const CxJsonValue *value); -void client_init(MessageHandler *handler); +void client_init(UiMessageHandler *handler); void client_msg_received(cxmutstr msg); diff -r 9b5948aa5b90 -r cc23aad6335e configure --- a/configure Sun Nov 30 18:17:49 2025 +0100 +++ b/configure Sun Nov 30 21:12:00 2025 +0100 @@ -85,39 +85,21 @@ printhelp() { echo "Usage: $0 [OPTIONS]..." - cat << __EOF__ -Installation directories: - --prefix=PREFIX path prefix for architecture-independent files - [$prefix] - --exec-prefix=EPREFIX path prefix for architecture-dependent files - [PREFIX] - - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR system configuration files [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR run-time variable data [LOCALSTATEDIR/run] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --mandir=DIR man documentation [DATAROOTDIR/man] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + echo 'Configuration:' + cat << '__EOF__' Build Types: --debug add extra compile flags for debug builds --release add extra compile flags for release builds Options: - --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|cocoa|motif) + --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|cocoa|motif|server) Optional Features: --enable-client __EOF__ + abort_configure } # create temporary directory @@ -133,26 +115,7 @@ 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 +# config variables # features @@ -163,32 +126,30 @@ for ARG in "$@" do case "$ARG" in - "--prefix="*) prefix=${ARG#--prefix=} ;; - "--exec-prefix="*) exec_prefix=${ARG#--exec-prefix=} ;; - "--bindir="*) bindir=${ARG#----bindir=} ;; - "--sbindir="*) sbindir=${ARG#--sbindir=} ;; - "--libdir="*) libdir=${ARG#--libdir=} ;; - "--libexecdir="*) libexecdir=${ARG#--libexecdir=} ;; - "--datarootdir="*) datarootdir=${ARG#--datarootdir=} ;; - "--datadir="*) datadir=${ARG#--datadir=} ;; - "--sysconfdir="*) sysconfdir=${ARG#--sysconfdir=} ;; - "--sharedstatedir="*) sharedstatedir=${ARG#--sharedstatedir=} ;; - "--localstatedir="*) localstatedir=${ARG#--localstatedir=} ;; - "--includedir="*) includedir=${ARG#--includedir=} ;; - "--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 ;; + "--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|gtk2legacy|qt5|qt4|cocoa|motif)"; abort_configure ;; + "--toolkit") echo "option '$ARG' needs a value:"; echo " $ARG=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|cocoa|motif|server)"; abort_configure ;; "--enable-client") FEATURE_CLIENT=on ;; "--disable-client") unset FEATURE_CLIENT ;; "-"*) echo "unknown option: $ARG"; abort_configure ;; esac done +# toolchain detection utilities +. make/toolchain.sh + +# check languages +lang_c= +lang_cpp= +if detect_cpp_compiler ; then + lang_cpp=1 +fi +if detect_c_compiler ; then + lang_c=1 +fi + # set defaults for dir variables @@ -199,67 +160,76 @@ : ${libexecdir:='${exec_prefix}/libexec'} : ${datarootdir:='${prefix}/share'} : ${datadir:='${datarootdir}'} -: ${sysconfdir:='${prefix}/etc'} : ${sharedstatedir:='${prefix}/com'} -: ${localstatedir:='${prefix}/var'} -: ${runstatedir:='${localstatedir}/run'} +if [ -z "$sysconfdir" ]; then + if [ "$prefix" = '/usr' ]; then + sysconfdir='/etc' + else + sysconfdir='${prefix}/etc' + fi +fi +if [ -z "$localstatedir" ]; then + if [ "$prefix" = '/usr' ]; then + localstatedir='/var' + else + localstatedir='${prefix}/var' + fi +fi +if [ -z "$runstatedir" ]; then + if [ "$prefix" = '/usr' ]; then + runstatedir='/var/run' + else + runstatedir='${prefix}/var' + fi +fi : ${includedir:='${prefix}/include'} : ${infodir:='${datarootdir}/info'} : ${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 +CONFIG_SITE_OK=0 if [ -n "$CONFIG_SITE" ]; then # CONFIG_SITE may contain space separated file names for cs in $CONFIG_SITE; do printf "loading defaults from $cs... " - . "$cs" - echo ok + if [ -f "$cs" ]; then + . "$cs" + echo ok + CONFIG_SITE_OK=1 + break + else + echo "not found" + fi done elif [ -f "$prefix/share/config.site" ]; then printf "loading site defaults... " . "$prefix/share/config.site" echo ok + CONFIG_SITE_OK=1 elif [ -f "$prefix/etc/config.site" ]; then printf "loading site defaults... " . "$prefix/etc/config.site" echo ok -else + CONFIG_SITE_OK=1 +fi + +if [ $CONFIG_SITE_OK -eq 0 ]; then # 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 - : + if [ "$libdir" = '${exec_prefix}/lib' ] ; then + if [ "$TOOLCHAIN_WSIZE" = "64" ] ; then + if [ "$OS" = "SunOS" ]; then + [ -d "${exec_prefix}/lib/64" ] && libdir='${exec_prefix}/lib/64' else - # if it does not, maybe a lib32 exists - test -d "${exec_prefix}/lib32" && libdir='${exec_prefix}/lib32' + [ -d "${exec_prefix}/lib64" ] && libdir='${exec_prefix}/lib64' 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 + elif [ "$TOOLCHAIN_WSIZE" = "32" ] ; then + if [ "$OS" = "SunOS" ]; then + [ -d "${exec_prefix}/lib/32" ] && libdir='${exec_prefix}/lib/32' + else + [ -d "${exec_prefix}/lib32" ] && libdir='${exec_prefix}/lib32' + fi fi fi fi @@ -267,40 +237,14 @@ # generate vars.mk cat > "$TEMP_DIR/vars.mk" << __EOF__ -prefix=$prefix -exec_prefix=$exec_prefix -bindir=$bindir -sbindir=$sbindir -libdir=$libdir -libexecdir=$libexecdir -datarootdir=$datarootdir -datadir=$datadir -sysconfdir=$sysconfdir -sharedstatedir=$sharedstatedir -localstatedir=$localstatedir -runstatedir=$runstatedir -includedir=$includedir -infodir=$infodir -mandir=$mandir -localedir=$localedir __EOF__ -# toolchain detection utilities -. make/toolchain.sh # # DEPENDENCIES # -# check languages -lang_c= -lang_cpp= -if detect_cpp_compiler ; then - lang_cpp=1 -fi -if detect_c_compiler ; then - lang_c=1 -fi + # create buffer for make variables required by dependencies echo > "$TEMP_DIR/make.mk" @@ -326,6 +270,22 @@ fi } +dependency_error_server() +{ + print_check_msg "$dep_checked_server" "checking for server... " + # dependency server + while true + do + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_SERVER -DUI_WEBVIEW" + print_check_msg "$dep_checked_server" "yes\n" + dep_checked_server=1 + return 1 + done + + print_check_msg "$dep_checked_server" "no\n" + dep_checked_server=1 + return 0 +} dependency_error_gtk2legacy() { print_check_msg "$dep_checked_gtk2legacy" "checking for gtk2legacy... " @@ -364,7 +324,7 @@ if [ -z "$PKG_CONFIG" ]; then break fi - if which qmake-qt5 > /dev/null ; then + if which qmake-qt5 > /dev/null 2>&1 ; then : else break @@ -399,7 +359,7 @@ if [ -z "$PKG_CONFIG" ]; then break fi - if pkg-config --atleast-version=2.20 gtk+-2.0 > /dev/null ; then + if pkg-config --atleast-version=2.20 gtk+-2.0 > /dev/null 2>&1 ; then : else break @@ -944,6 +904,20 @@ __EOF__ return 0 } +checkopt_toolkit_server() +{ + VERR=0 + if dependency_error_server ; then + VERR=1 + fi + if [ $VERR -ne 0 ]; then + return 1 + fi + cat >> "$TEMP_DIR/make.mk" << __EOF__ +TOOLKIT = server +__EOF__ + return 0 +} # # TARGETS @@ -1090,10 +1064,18 @@ ERROR=1 DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" fi + elif [ "$OPT_TOOLKIT" = "server" ]; then + echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options + if checkopt_toolkit_server ; then + : + else + ERROR=1 + DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" + fi else echo echo "Invalid option value - usage:" - echo " --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|cocoa|motif)" + echo " --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|cocoa|motif|server)" abort_configure fi fi @@ -1153,7 +1135,7 @@ echo "configure finished" echo -echo "Toolchain" +echo "Toolchain:" echo " name: $TOOLCHAIN_NAME" if [ -n "$TOOLCHAIN_CC" ]; then echo " cc: $TOOLCHAIN_CC" @@ -1168,60 +1150,17 @@ echo " default C std: $TOOLCHAIN_CSTD" fi echo -echo "Build Config:" -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 "Config:" echo echo "Options:" cat "$TEMP_DIR/options" echo echo "Features:" +printf ' %-16s' 'client:' if [ -n "$FEATURE_CLIENT" ]; then -echo " client: on" + echo 'on' else -echo " client: off" + echo 'off' fi echo diff -r 9b5948aa5b90 -r cc23aad6335e make/configure.vm --- a/make/configure.vm Sun Nov 30 18:17:49 2025 +0100 +++ b/make/configure.vm Sun Nov 30 21:12:00 2025 +0100 @@ -86,27 +86,30 @@ printhelp() { echo "Usage: $0 [OPTIONS]..." - cat << __EOF__ -Installation directories: - --prefix=PREFIX path prefix for architecture-independent files - [${D}prefix] - --exec-prefix=EPREFIX path prefix for architecture-dependent files - [PREFIX] - - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR system configuration files [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR run-time variable data [LOCALSTATEDIR/run] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --mandir=DIR man documentation [DATAROOTDIR/man] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + echo 'Configuration:' +#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.overridable ) + if test -z "${D}${var.varName}__described__"; then + ${var.varName}__described__=1 + cat << '__EOF__' +${var.helpText} +__EOF__ + fi + #end + #end +fi +#end + cat << '__EOF__' Build Types: --debug add extra compile flags for debug builds @@ -115,7 +118,7 @@ Options: #foreach( $opt in $options ) - --${opt.argument}=${opt.valuesString} +${opt.helpText} #end #end #if( $features.size() > 0 ) @@ -127,6 +130,7 @@ #end __EOF__ + abort_configure } # create temporary directory @@ -142,26 +146,7 @@ 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 +# config variables #foreach( $cfg in $config ) if true \ #if( $cfg.platform ) @@ -171,12 +156,16 @@ && notisplatform "${np}" \ #end ; then + : #foreach( $var in $cfg.vars ) - #if( $var.exec ) - ${var.varName}=`${var.value}` - #else - ${var.varName}="${var.value}" - #end + if test -z "${D}${var.varName}__initialized__"; then + ${var.varName}__initialized__=1 + #if( $var.exec ) + ${var.varName}=`${var.value}` + #else + ${var.varName}='${var.value}' + #end + fi #end fi #end @@ -195,27 +184,17 @@ for ARG in "$@" do case "$ARG" in - "--prefix="*) prefix=${D}{ARG#--prefix=} ;; - "--exec-prefix="*) exec_prefix=${D}{ARG#--exec-prefix=} ;; - "--bindir="*) bindir=${D}{ARG#----bindir=} ;; - "--sbindir="*) sbindir=${D}{ARG#--sbindir=} ;; - "--libdir="*) libdir=${D}{ARG#--libdir=} ;; - "--libexecdir="*) libexecdir=${D}{ARG#--libexecdir=} ;; - "--datarootdir="*) datarootdir=${D}{ARG#--datarootdir=} ;; - "--datadir="*) datadir=${D}{ARG#--datadir=} ;; - "--sysconfdir="*) sysconfdir=${D}{ARG#--sysconfdir=} ;; - "--sharedstatedir="*) sharedstatedir=${D}{ARG#--sharedstatedir=} ;; - "--localstatedir="*) localstatedir=${D}{ARG#--localstatedir=} ;; - "--includedir="*) includedir=${D}{ARG#--includedir=} ;; - "--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" ;; + #foreach( $var in $vars ) + #if ($var.overridable) + "--${var.arg}="*) ${var.varName}=${D}{ARG#--${var.arg}=} ;; + #end + #end + "--help"*) printhelp ;; + "--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 ;; + "--${opt.arg}="*) ${opt.varName}=${D}{ARG#--${opt.arg}=} ;; + "--${opt.arg}") echo "option '$ARG' needs a value:"; echo " $ARG=${opt.valuesString}"; abort_configure ;; #end #foreach( $feature in $features ) "--enable-${feature.arg}") ${feature.varName}=on ;; @@ -225,6 +204,18 @@ esac done +# toolchain detection utilities +. make/toolchain.sh + +# check languages +lang_c= +lang_cpp= +#foreach( $lang in $languages ) +if detect_${lang}_compiler ; then + lang_${lang}=1 +fi +#end + ## Begin unparsed content. ** #[[ @@ -236,67 +227,76 @@ : ${libexecdir:='${exec_prefix}/libexec'} : ${datarootdir:='${prefix}/share'} : ${datadir:='${datarootdir}'} -: ${sysconfdir:='${prefix}/etc'} : ${sharedstatedir:='${prefix}/com'} -: ${localstatedir:='${prefix}/var'} -: ${runstatedir:='${localstatedir}/run'} +if [ -z "$sysconfdir" ]; then + if [ "$prefix" = '/usr' ]; then + sysconfdir='/etc' + else + sysconfdir='${prefix}/etc' + fi +fi +if [ -z "$localstatedir" ]; then + if [ "$prefix" = '/usr' ]; then + localstatedir='/var' + else + localstatedir='${prefix}/var' + fi +fi +if [ -z "$runstatedir" ]; then + if [ "$prefix" = '/usr' ]; then + runstatedir='/var/run' + else + runstatedir='${prefix}/var' + fi +fi : ${includedir:='${prefix}/include'} : ${infodir:='${datarootdir}/info'} : ${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 +CONFIG_SITE_OK=0 if [ -n "$CONFIG_SITE" ]; then # CONFIG_SITE may contain space separated file names for cs in $CONFIG_SITE; do printf "loading defaults from $cs... " - . "$cs" - echo ok + if [ -f "$cs" ]; then + . "$cs" + echo ok + CONFIG_SITE_OK=1 + break + else + echo "not found" + fi done elif [ -f "$prefix/share/config.site" ]; then printf "loading site defaults... " . "$prefix/share/config.site" echo ok + CONFIG_SITE_OK=1 elif [ -f "$prefix/etc/config.site" ]; then printf "loading site defaults... " . "$prefix/etc/config.site" echo ok -else + CONFIG_SITE_OK=1 +fi + +if [ $CONFIG_SITE_OK -eq 0 ]; then # 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 - : + if [ "$libdir" = '${exec_prefix}/lib' ] ; then + if [ "$TOOLCHAIN_WSIZE" = "64" ] ; then + if [ "$OS" = "SunOS" ]; then + [ -d "${exec_prefix}/lib/64" ] && libdir='${exec_prefix}/lib/64' else - # if it does not, maybe a lib32 exists - test -d "${exec_prefix}/lib32" && libdir='${exec_prefix}/lib32' + [ -d "${exec_prefix}/lib64" ] && libdir='${exec_prefix}/lib64' 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 + elif [ "$TOOLCHAIN_WSIZE" = "32" ] ; then + if [ "$OS" = "SunOS" ]; then + [ -d "${exec_prefix}/lib/32" ] && libdir='${exec_prefix}/lib/32' + else + [ -d "${exec_prefix}/lib32" ] && libdir='${exec_prefix}/lib32' + fi fi fi fi @@ -305,42 +305,17 @@ # generate vars.mk cat > "$TEMP_DIR/vars.mk" << __EOF__ -prefix=$prefix -exec_prefix=$exec_prefix -bindir=$bindir -sbindir=$sbindir -libdir=$libdir -libexecdir=$libexecdir -datarootdir=$datarootdir -datadir=$datadir -sysconfdir=$sysconfdir -sharedstatedir=$sharedstatedir -localstatedir=$localstatedir -runstatedir=$runstatedir -includedir=$includedir -infodir=$infodir -mandir=$mandir -localedir=$localedir #foreach( $var in $vars ) ${var.varName}=${D}${var.varName} #end __EOF__ -# toolchain detection utilities -. make/toolchain.sh # # DEPENDENCIES # -# check languages -lang_c= -lang_cpp= -#foreach( $lang in $languages ) -if detect_${lang}_compiler ; then - lang_${lang}=1 -fi -#end + # create buffer for make variables required by dependencies echo > "$TEMP_DIR/make.mk" @@ -400,7 +375,7 @@ fi #end #foreach( $test in $sub.tests ) - if $test > /dev/null ; then + if $test > /dev/null 2>&1 ; then : else break @@ -502,7 +477,6 @@ #foreach( $flags in $dependency.flags ) #if( $flags.exec ) - $flags.value > /dev/null if tmp_flags=`$flags.value` ; then TEMP_$flags.varName="$TEMP_$flags.varName $tmp_flags" else @@ -652,9 +626,9 @@ #end #foreach( $opt in $target.options ) -# Option: --${opt.argument} +# Option: --${opt.arg} if [ -z "${D}${opt.varName}" ]; then - echo "auto-detecting option '${opt.argument}'" + echo "auto-detecting option '${opt.arg}'" SAVED_ERROR="$ERROR" SAVED_DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED" ERROR=1 @@ -665,7 +639,7 @@ if isplatform "$optdef.platform"; then #end if $optdef.func ; then - echo " ${opt.argument}: ${optdef.valueName}" >> "$TEMP_DIR/options" + echo " ${opt.arg}: ${optdef.valueName}" >> "$TEMP_DIR/options" ERROR=0 break fi @@ -677,28 +651,28 @@ done if [ $ERROR -ne 0 ]; then SAVED_ERROR=1 - SAVED_DEPENDENCIES_FAILED="option '${opt.argument}' $SAVED_DEPENDENCIES_FAILED" + SAVED_DEPENDENCIES_FAILED="option '${opt.arg}' $SAVED_DEPENDENCIES_FAILED" fi ERROR="$SAVED_ERROR" DEPENDENCIES_FAILED="$SAVED_DEPENDENCIES_FAILED" else - echo "checking option ${opt.argument} = ${D}${opt.varName}" + echo "checking option ${opt.arg} = ${D}${opt.varName}" if false; then false #foreach( $optval in $opt.values ) elif [ "${D}${opt.varName}" = "${optval.value}" ]; then - echo " ${opt.argument}: ${D}${opt.varName}" >> $TEMP_DIR/options + echo " ${opt.arg}: ${D}${opt.varName}" >> $TEMP_DIR/options if $optval.func ; then : else ERROR=1 - DEPENDENCIES_FAILED="option '${opt.argument}' $DEPENDENCIES_FAILED" + DEPENDENCIES_FAILED="option '${opt.arg}' $DEPENDENCIES_FAILED" fi #end else echo echo "Invalid option value - usage:" - echo " --${opt.argument}=${opt.valuesString}" + echo " --${opt.arg}=${opt.valuesString}" abort_configure fi fi @@ -726,7 +700,7 @@ echo "configure finished" echo -echo "Toolchain" +echo "Toolchain:" echo " name: $TOOLCHAIN_NAME" if [ -n "$TOOLCHAIN_CC" ]; then echo " cc: $TOOLCHAIN_CC" @@ -741,51 +715,13 @@ echo " default C std: $TOOLCHAIN_CSTD" fi echo -echo "Build Config:" -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 "Config:" +#foreach( $var in $vars ) +#if ($var.overridable) + printf ' %-16s' '${var.arg}:' + echo "${D}${var.varName}" +#end +#end #if ( $options.size() > 0 ) echo echo "Options:" @@ -795,10 +731,11 @@ echo echo "Features:" #foreach( $feature in $features ) +printf ' %-16s' '$feature.name:' if [ -n "${D}${feature.varName}" ]; then -echo " $feature.name: on" + echo 'on' else -echo " $feature.name: off" + echo 'off' fi #end #end diff -r 9b5948aa5b90 -r cc23aad6335e make/project.xml --- a/make/project.xml Sun Nov 30 18:17:49 2025 +0100 +++ b/make/project.xml Sun Nov 30 21:12:00 2025 +0100 @@ -1,5 +1,5 @@ - + c LD = \$(CC) @@ -96,6 +96,10 @@ + + -DUI_SERVER -DUI_WEBVIEW + + OBJ_EXT = .o LIB_EXT = .a @@ -165,6 +169,10 @@ motif TOOLKIT = motif + + server + TOOLKIT = server + diff -r 9b5948aa5b90 -r cc23aad6335e make/toolchain.sh --- a/make/toolchain.sh Sun Nov 30 18:17:49 2025 +0100 +++ b/make/toolchain.sh Sun Nov 30 21:12:00 2025 +0100 @@ -24,8 +24,9 @@ check_c_compiler() { - command -v "$1" >/dev/null 2>&1 - if [ $? -ne 0 ] ; then + if command -v "$1" >/dev/null 2>&1 ; then + : + else return 1 fi cat > "$TEMP_DIR/test.c" << __EOF__ @@ -56,8 +57,9 @@ check_cpp_compiler() { - command -v "$1" >/dev/null 2>&1 - if [ $? -ne 0 ] ; then + if command -v "$1" >/dev/null 2>&1 ; then + : + else return 1 fi cat > "$TEMP_DIR/test.cpp" << __EOF__ diff -r 9b5948aa5b90 -r cc23aad6335e make/uwproj.xsd --- a/make/uwproj.xsd Sun Nov 30 18:17:49 2025 +0100 +++ b/make/uwproj.xsd Sun Nov 30 21:12:00 2025 +0100 @@ -3,7 +3,7 @@ xmlns="http://unixwork.de/uwproj" targetNamespace="http://unixwork.de/uwproj" elementFormDefault="qualified" - version="0.3" + version="0.4" > @@ -29,23 +29,61 @@

The configuration section. - Consists of an arbitrary number of var elements. + Consists of an arbitrary number of var elements and pre-defined elements for + standard installation directories. If you want to use standard installation directories, you + must list the wanted variables here.

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. + When multiple config sections have a matching filter, and declare the same variables, the settings + of the first matching config section will be used for the affected variables.

+ + + + + + + + + + + + + + + + + + + + The definition of a standard configuration variable. +

+ You may customize the value and the help text, + but the variable name and the option name are pre-defined. +

+
+
+ + + + + + +
+ @@ -55,14 +93,23 @@ written to the resulting config file (in contrast to make variables, which are only written to the config file). The name attribute is mandatory, the value is defined by the text body of the element. - The optional Boolean exec attribute (false by default) controls, whether the entire - definition is automatically executed under command substitution. + The optional Boolean exec attribute (false by default) controls, whether value denotes + a command which shall be executed at configuration time to produce the value. + With option and option-help you can control how the variable can be + overridden on the command line. When you don't specify either of those attributes, no command + line option will be generated. When you provide a option-help, but do not specify the + option name, a name is generated. + You can use the string %default in your help text when you want to show the default + value in the text. When exec is used, the default will not be resolved in the help + text and instead the command is shown (to avoid breaking the formatting).

+ + @@ -228,7 +275,9 @@ Declares a configuration option. The option argument name is specified with the arg attribute. - Then, the children of this element specify possible values by defining the conditions + Optionally, a description for the help text of the resulting configure script can be specified by + a desc element. + Then, the next children of this element specify possible values by defining the conditions (in terms of dependencies) and effects (in terms of defines and make variables) of each value. Finally, a set of defaults is specified which supposed to automagically select the most appropriate value for a specific platform under the available dependencies (in case the option is not @@ -236,6 +285,7 @@ + diff -r 9b5948aa5b90 -r cc23aad6335e ui/common/message.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/common/message.c Sun Nov 30 21:12:00 2025 +0100 @@ -0,0 +1,174 @@ +/* + * 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 +#include +#include + +#include "message.h" + +UiMessageHandler* uic_simple_msg_handler(int in, int out, msg_received_callback callback) { + UiSimpleMessageHandler *handler = malloc(sizeof(UiSimpleMessageHandler)); + handler->handler.start = uic_simple_msg_handler_start; + handler->handler.stop = uic_simple_msg_handler_stop; + handler->handler.send = uic_simple_msg_handler_send; + handler->handler.callback = callback; + handler->in = in; + handler->out = out; + handler->outbuf = cxBufferCreate(NULL, 4096, NULL, CX_BUFFER_FREE_CONTENTS | CX_BUFFER_AUTO_EXTEND); + handler->stop = 0; + pthread_mutex_init(&handler->queue_lock, NULL); + pthread_mutex_init(&handler->avlbl_lock, NULL); + pthread_cond_init(&handler->available, NULL); + return (UiMessageHandler*)handler; +} + +int uic_simple_msg_handler_start(UiMessageHandler *handler) { + UiSimpleMessageHandler *sh = (UiSimpleMessageHandler*)handler; + if(pthread_create(&sh->in_thread, NULL, uic_simple_msg_handler_in_thread, sh)) { + return 1; + } + if(pthread_create(&sh->out_thread, NULL, uic_simple_msg_handler_out_thread, sh)) { + return 1; + } + return 0; +} + +int uic_simple_msg_handler_stop(UiMessageHandler *handler) { + UiSimpleMessageHandler *sh = (UiSimpleMessageHandler*)handler; + pthread_mutex_lock(&sh->queue_lock); + sh->stop = 0; + pthread_cond_signal(&sh->available); + pthread_mutex_unlock(&sh->queue_lock); + close(sh->in); + sh->in = -1; + + pthread_join(sh->in_thread, NULL); + pthread_join(sh->out_thread, NULL); + + return 0; +} + +int uic_simple_msg_handler_send(UiMessageHandler *handler, cxstring msg) { + UiSimpleMessageHandler *sh = (UiSimpleMessageHandler*)handler; + pthread_mutex_lock(&sh->queue_lock); + cxBufferWrite(msg.ptr, 1, msg.length, sh->outbuf); + pthread_cond_signal(&sh->available); + pthread_mutex_unlock(&sh->queue_lock); + return 0; +} + +#define HEADERBUF_SIZE 64 + +void* uic_simple_msg_handler_in_thread(void *data) { + UiSimpleMessageHandler *handler = data; + + char *msg = NULL; + size_t msg_size = 0; + size_t msg_pos = 0; // currently received message length + + char headerbuf[HEADERBUF_SIZE]; + size_t headerpos = 0; + + char buf[2048]; + ssize_t r; + while((r = read(handler->in, buf, 2024)) > 0) { + char *buffer = buf; + size_t available = r; + + while(available > 0) { + if(msg) { + // read message + size_t need = msg_size - msg_pos; + size_t cplen = r > need ? need : available; + memcpy(msg+msg_pos, buffer, cplen); + buffer += cplen; + available -= cplen; + msg_pos += cplen; + if(msg_pos == msg_size) { + // message complete + //fprintf(stderr, "send: %.*s\n", (int)msg_size, msg); + if(handler->handler.callback) { + handler->handler.callback(cx_mutstrn(msg, msg_size)); + } + msg = NULL; + msg_size = 0; + msg_pos = 0; + } + } else { + size_t header_max = HEADERBUF_SIZE - headerpos - 1; + if(header_max > available) { + header_max = available; + } + // search for line break + int i; + int header_complete = 0; + for(i=0;i= HEADERBUF_SIZE) { + fprintf(stderr, "Error: message header too big\n"); + exit(-1); + } + } + } + + + } + perror("error"); + fprintf(stderr, "stop simple_msg_handler_in_thread\n"); + + return NULL; +} + +void* uic_simple_msg_handler_out_thread(void *data) { + UiSimpleMessageHandler *handler = data; + + return NULL; +} diff -r 9b5948aa5b90 -r cc23aad6335e ui/common/message.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/common/message.h Sun Nov 30 21:12:00 2025 +0100 @@ -0,0 +1,83 @@ +/* + * 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_MESSAGE_H +#define UIC_MESSAGE_H + +#include +#include +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct UiMessageHandler UiMessageHandler; + +typedef void(*msg_received_callback)(cxmutstr msg); + +struct UiMessageHandler { + int (*start)(UiMessageHandler *handler); + int (*stop)(UiMessageHandler *handler); + int (*send)(UiMessageHandler *handler, cxstring msg); + + msg_received_callback callback; +}; + +typedef struct UiSimpleMessageHandler { + UiMessageHandler handler; + int in; + int out; + pthread_t in_thread; + pthread_t out_thread; + pthread_mutex_t queue_lock; + pthread_mutex_t avlbl_lock; + pthread_cond_t available; + CxBuffer *outbuf; + int stop; +} UiSimpleMessageHandler; + +UiMessageHandler* uic_simple_msg_handler(int in, int out, msg_received_callback callback); +int uic_simple_msg_handler_start(UiMessageHandler *handler); +int uic_simple_msg_handler_stop(UiMessageHandler *handler); +int uic_simple_msg_handler_send(UiMessageHandler *handler, cxstring msg); + +void* uic_simple_msg_handler_in_thread(void *data); +void* uic_simple_msg_handler_out_thread(void *data); + + +#ifdef __cplusplus +} +#endif + +#endif /* UIC_MESSAGE_H */ + diff -r 9b5948aa5b90 -r cc23aad6335e ui/common/objs.mk --- a/ui/common/objs.mk Sun Nov 30 18:17:49 2025 +0100 +++ b/ui/common/objs.mk Sun Nov 30 21:12:00 2025 +0100 @@ -43,6 +43,7 @@ COMMON_OBJ += args$(OBJ_EXT) COMMON_OBJ += wrapper$(OBJ_EXT) COMMON_OBJ += utils$(OBJ_EXT) +COMMON_OBJ += message$(OBJ_EXT) TOOLKITOBJS += $(COMMON_OBJ:%=$(COMMON_OBJPRE)uic_%) TOOLKITSOURCE += $(COMMON_OBJ:%$(OBJ_EXT)=common/%.c) diff -r 9b5948aa5b90 -r cc23aad6335e ui/server/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/server/Makefile Sun Nov 30 21:12:00 2025 +0100 @@ -0,0 +1,36 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2012 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +$(SERVER_OBJPRE)%.o: server/%.c + $(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 -r 9b5948aa5b90 -r cc23aad6335e ui/server/objs.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/server/objs.mk Sun Nov 30 21:12:00 2025 +0100 @@ -0,0 +1,35 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2012 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +SERVER_SRC_DIR = ui/server/ +SERVER_OBJPRE = $(OBJ_DIR)$(SERVER_SRC_DIR) + +SERVEROBJ = toolkit.o + +TOOLKITOBJS += $(SERVEROBJ:%=$(SERVER_OBJPRE)%) +TOOLKITSOURCE += $(SERVEROBJ:%.o=SERVER/%.c) diff -r 9b5948aa5b90 -r cc23aad6335e ui/server/toolkit.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/server/toolkit.c Sun Nov 30 21:12:00 2025 +0100 @@ -0,0 +1,36 @@ +/* + * 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 +#include +#include +#include + +#include "toolkit.h" + + diff -r 9b5948aa5b90 -r cc23aad6335e ui/server/toolkit.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/server/toolkit.h Sun Nov 30 21:12:00 2025 +0100 @@ -0,0 +1,48 @@ +/* + * 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 TOOLKIT_H +#define TOOLKIT_H + +#include +#include "../ui/toolkit.h" +#include "../common/context.h" +#include "../common/object.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif /* TOOLKIT_H */ + diff -r 9b5948aa5b90 -r cc23aad6335e ui/ui/toolkit.h --- a/ui/ui/toolkit.h Sun Nov 30 18:17:49 2025 +0100 +++ b/ui/ui/toolkit.h Sun Nov 30 21:12:00 2025 +0100 @@ -146,6 +146,12 @@ #endif +#elif UI_SERVER + +#define UIWIDGET void* +#define UIWINDOW void* +#define UIMENU void* + #endif #ifndef TRUE diff -r 9b5948aa5b90 -r cc23aad6335e ui/ui/widget.h --- a/ui/ui/widget.h Sun Nov 30 18:17:49 2025 +0100 +++ b/ui/ui/widget.h Sun Nov 30 21:12:00 2025 +0100 @@ -64,6 +64,8 @@ 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); +#elif defined(UI_SERVER) +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);