add option to select a specific curses implementation

Mon, 31 Aug 2026 15:49:31 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 31 Aug 2026 15:49:31 +0200
changeset 197
9cbd4f09a22f
parent 196
168a38ae1b2d
child 198
7850e9a6f007

add option to select a specific curses implementation

resolves #981

configure file | annotate | diff | comparison | revisions
make/chklib.sh file | annotate | diff | comparison | revisions
make/project.xml file | annotate | diff | comparison | revisions
src/input.h file | annotate | diff | comparison | revisions
src/main.c file | annotate | diff | comparison | revisions
test/Makefile file | annotate | diff | comparison | revisions
--- a/configure	Tue Aug 25 22:25:33 2026 +0200
+++ b/configure	Mon Aug 31 15:49:31 2026 +0200
@@ -99,6 +99,10 @@
   --debug                 add extra compile flags for debug builds
   --release               add extra compile flags for release builds
 
+Options:
+  --curses=(ncursesw|cursesw|ncurses|curses)
+                          The curses implementation to use.
+
 Optional Features:
   --enable-asan           address sanitizer
   --enable-strict-errors  treat compiler warnings as errors
@@ -175,6 +179,8 @@
         "--help"*) printhelp ;;
         "--debug") BUILD_TYPE="debug" ;;
         "--release") BUILD_TYPE="release" ;;
+        "--curses="*) OPT_CURSES=${ARG#--curses=} ;;
+        "--curses") echo "option '$ARG' needs a value:"; echo "  $ARG=(ncursesw|cursesw|ncurses|curses)"; abort_configure ;;
         "--enable-asan") FEATURE_ASAN=on ;;
         "--disable-asan") unset FEATURE_ASAN ;;
         "--enable-strict-errors") FEATURE_STRICT_ERRORS=on ;;
@@ -339,10 +345,10 @@
     dep_checked_asan=1
     return 0
 }
-dependency_error_ncurses()
+dependency_error_ncursesw()
 {
-    print_check_msg "$dep_checked_ncurses" "checking for ncurses... "
-    # dependency ncurses
+    print_check_msg "$dep_checked_ncursesw" "checking for ncursesw... "
+    # dependency ncursesw
     while true
     do
         if [ -z "$PKG_CONFIG" ]; then
@@ -354,6 +360,172 @@
         else
             break
         fi
+        print_check_msg "$dep_checked_ncursesw" "yes\n"
+        dep_checked_ncursesw=1
+        return 1
+    done
+
+    # dependency ncursesw
+    while true
+    do
+        if ./make/chklib.sh ncursesw > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        if ./make/chklib.sh tinfo > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_LDFLAGS="$TEMP_LDFLAGS -lncursesw -ltinfo"
+        print_check_msg "$dep_checked_ncursesw" "yes\n"
+        dep_checked_ncursesw=1
+        return 1
+    done
+
+    # dependency ncursesw
+    while true
+    do
+        if ./make/chklib.sh ncursesw > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_LDFLAGS="$TEMP_LDFLAGS -lncursesw"
+        print_check_msg "$dep_checked_ncursesw" "yes\n"
+        dep_checked_ncursesw=1
+        return 1
+    done
+
+    print_check_msg "$dep_checked_ncursesw" "no\n"
+    dep_checked_ncursesw=1
+    return 0
+}
+dependency_error_curses()
+{
+    print_check_msg "$dep_checked_curses" "checking for curses... "
+    # dependency curses
+    while true
+    do
+        if [ -z "$PKG_CONFIG" ]; then
+            break
+        fi
+        if test_pkg_config "curses" "" "" "" ; then
+            TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags curses`"
+            TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs curses`"
+        else
+            break
+        fi
+        print_check_msg "$dep_checked_curses" "yes\n"
+        dep_checked_curses=1
+        return 1
+    done
+
+    # dependency curses
+    while true
+    do
+        if ./make/chklib.sh curses > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_LDFLAGS="$TEMP_LDFLAGS -lcurses"
+        print_check_msg "$dep_checked_curses" "yes\n"
+        dep_checked_curses=1
+        return 1
+    done
+
+    print_check_msg "$dep_checked_curses" "no\n"
+    dep_checked_curses=1
+    return 0
+}
+dependency_error_cursesw()
+{
+    print_check_msg "$dep_checked_cursesw" "checking for cursesw... "
+    # dependency cursesw
+    while true
+    do
+        if [ -z "$PKG_CONFIG" ]; then
+            break
+        fi
+        if test_pkg_config "cursesw" "" "" "" ; then
+            TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags cursesw`"
+            TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs cursesw`"
+        else
+            break
+        fi
+        print_check_msg "$dep_checked_cursesw" "yes\n"
+        dep_checked_cursesw=1
+        return 1
+    done
+
+    # dependency cursesw
+    while true
+    do
+        if ./make/chklib.sh cursesw > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_LDFLAGS="$TEMP_LDFLAGS -lcursesw"
+        print_check_msg "$dep_checked_cursesw" "yes\n"
+        dep_checked_cursesw=1
+        return 1
+    done
+
+    print_check_msg "$dep_checked_cursesw" "no\n"
+    dep_checked_cursesw=1
+    return 0
+}
+dependency_error_ncurses()
+{
+    print_check_msg "$dep_checked_ncurses" "checking for ncurses... "
+    # dependency ncurses
+    while true
+    do
+        if [ -z "$PKG_CONFIG" ]; then
+            break
+        fi
+        if test_pkg_config "ncurses" "" "" "" ; then
+            TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags ncurses`"
+            TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs ncurses`"
+        else
+            break
+        fi
+        print_check_msg "$dep_checked_ncurses" "yes\n"
+        dep_checked_ncurses=1
+        return 1
+    done
+
+    # dependency ncurses
+    while true
+    do
+        if ./make/chklib.sh ncurses > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        if ./make/chklib.sh tinfo > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_LDFLAGS="$TEMP_LDFLAGS -lncurses -ltinfo"
+        print_check_msg "$dep_checked_ncurses" "yes\n"
+        dep_checked_ncurses=1
+        return 1
+    done
+
+    # dependency ncurses
+    while true
+    do
+        if ./make/chklib.sh ncurses > /dev/null 2>&1 ; then
+            :
+        else
+            break
+        fi
+        TEMP_LDFLAGS="$TEMP_LDFLAGS -lncurses"
         print_check_msg "$dep_checked_ncurses" "yes\n"
         dep_checked_ncurses=1
         return 1
@@ -412,6 +584,54 @@
 #
 # OPTION VALUES
 #
+checkopt_curses_ncursesw()
+{
+    VERR=0
+    if dependency_error_ncursesw ; then
+        VERR=1
+    fi
+    if [ $VERR -ne 0 ]; then
+        return 1
+    fi
+    return 0
+}
+checkopt_curses_cursesw()
+{
+    VERR=0
+    if dependency_error_cursesw ; then
+        VERR=1
+    fi
+    if [ $VERR -ne 0 ]; then
+        return 1
+    fi
+    return 0
+}
+checkopt_curses_ncurses()
+{
+    VERR=0
+    if dependency_error_ncurses ; then
+        VERR=1
+    fi
+    if [ $VERR -ne 0 ]; then
+        return 1
+    fi
+        TEMP_CFLAGS="$TEMP_CFLAGS -DDISABLE_UNICODE"
+        TEMP_CXXFLAGS="$TEMP_CXXFLAGS -DDISABLE_UNICODE"
+    return 0
+}
+checkopt_curses_curses()
+{
+    VERR=0
+    if dependency_error_curses ; then
+        VERR=1
+    fi
+    if [ $VERR -ne 0 ]; then
+        return 1
+    fi
+        TEMP_CFLAGS="$TEMP_CFLAGS -DDISABLE_UNICODE"
+        TEMP_CXXFLAGS="$TEMP_CXXFLAGS -DDISABLE_UNICODE"
+    return 0
+}
 
 #
 # TARGETS
@@ -424,10 +644,6 @@
 TEMP_CXXFLAGS=
 TEMP_LDFLAGS=
 
-if dependency_error_ncurses; then
-    DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED ncurses "
-    ERROR=1
-fi
 
 # Features
 if [ -n "$FEATURE_ASAN" ]; then
@@ -464,6 +680,85 @@
     :
 fi
 
+# Option: --curses
+if [ -z "$OPT_CURSES" ]; then
+    echo "auto-detecting option 'curses'"
+    SAVED_ERROR="$ERROR"
+    SAVED_DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED"
+    ERROR=1
+    while true
+    do
+        if checkopt_curses_ncursesw ; then
+            echo "  curses: ncursesw" >> "$TEMP_DIR/options"
+            ERROR=0
+            break
+        fi
+        if checkopt_curses_cursesw ; then
+            echo "  curses: cursesw" >> "$TEMP_DIR/options"
+            ERROR=0
+            break
+        fi
+        if checkopt_curses_ncurses ; then
+            echo "  curses: ncurses" >> "$TEMP_DIR/options"
+            ERROR=0
+            break
+        fi
+        if checkopt_curses_curses ; then
+            echo "  curses: curses" >> "$TEMP_DIR/options"
+            ERROR=0
+            break
+        fi
+        break
+    done
+    if [ $ERROR -ne 0 ]; then
+        SAVED_ERROR=1
+        SAVED_DEPENDENCIES_FAILED="option 'curses' $SAVED_DEPENDENCIES_FAILED"
+    fi
+    ERROR="$SAVED_ERROR"
+    DEPENDENCIES_FAILED="$SAVED_DEPENDENCIES_FAILED"
+else
+    echo "checking option curses = $OPT_CURSES"
+    if false; then
+        false
+    elif [ "$OPT_CURSES" = "ncursesw" ]; then
+        echo "  curses: $OPT_CURSES" >> $TEMP_DIR/options
+        if checkopt_curses_ncursesw ; then
+            :
+        else
+            ERROR=1
+            DEPENDENCIES_FAILED="option 'curses' $DEPENDENCIES_FAILED"
+        fi
+    elif [ "$OPT_CURSES" = "cursesw" ]; then
+        echo "  curses: $OPT_CURSES" >> $TEMP_DIR/options
+        if checkopt_curses_cursesw ; then
+            :
+        else
+            ERROR=1
+            DEPENDENCIES_FAILED="option 'curses' $DEPENDENCIES_FAILED"
+        fi
+    elif [ "$OPT_CURSES" = "ncurses" ]; then
+        echo "  curses: $OPT_CURSES" >> $TEMP_DIR/options
+        if checkopt_curses_ncurses ; then
+            :
+        else
+            ERROR=1
+            DEPENDENCIES_FAILED="option 'curses' $DEPENDENCIES_FAILED"
+        fi
+    elif [ "$OPT_CURSES" = "curses" ]; then
+        echo "  curses: $OPT_CURSES" >> $TEMP_DIR/options
+        if checkopt_curses_curses ; then
+            :
+        else
+            ERROR=1
+            DEPENDENCIES_FAILED="option 'curses' $DEPENDENCIES_FAILED"
+        fi
+    else
+        echo
+        echo "Invalid option value - usage:"
+        echo "  --curses=(ncursesw|cursesw|ncurses|curses)"
+        abort_configure
+    fi
+fi
 
 if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then
     echo "CFLAGS  += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk"
@@ -505,6 +800,9 @@
     echo "Config:"
 fi
 echo
+echo "Options:"
+cat "$TEMP_DIR/options"
+echo
 echo "Features:"
 printf '  %-16s' 'asan:'
 if [ -n "$FEATURE_ASAN" ]; then
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/chklib.sh	Mon Aug 31 15:49:31 2026 +0200
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+libname="$1"
+cc="$CC"
+if test -z "$cc"; then cc=cc; fi
+if test -z "$libname"; then exit 1; fi
+
+echo 'int main(){return 0;}' > .chklib-test.c
+
+if $cc -o /dev/null .chklib-test.c "-l$libname" ; then
+  rm .chklib-test.c
+  exit 0
+else
+  rm .chklib-test.c
+  exit 1
+fi
--- a/make/project.xml	Tue Aug 25 22:25:33 2026 +0200
+++ b/make/project.xml	Mon Aug 31 15:49:31 2026 +0200
@@ -14,15 +14,75 @@
     <dependency>
         <lang>c</lang>
     </dependency>
-    <dependency name="ncurses">
+
+    <dependency name="ncursesw">
         <pkgconfig>ncursesw</pkgconfig>
     </dependency>
+    <dependency name="ncursesw">
+        <test>./make/chklib.sh ncursesw</test>
+        <test>./make/chklib.sh tinfo</test>
+        <ldflags>-lncursesw -ltinfo</ldflags>
+    </dependency>
+    <dependency name="ncursesw">
+        <test>./make/chklib.sh ncursesw</test>
+        <ldflags>-lncursesw</ldflags>
+    </dependency>
+
+    <dependency name="cursesw">
+        <pkgconfig>cursesw</pkgconfig>
+    </dependency>
+    <dependency name="cursesw">
+        <test>./make/chklib.sh cursesw</test>
+        <ldflags>-lcursesw</ldflags>
+    </dependency>
+
+    <dependency name="curses">
+        <pkgconfig>curses</pkgconfig>
+    </dependency>
+    <dependency name="curses">
+        <test>./make/chklib.sh curses</test>
+        <ldflags>-lcurses</ldflags>
+    </dependency>
+
+    <dependency name="ncurses">
+        <pkgconfig>ncurses</pkgconfig>
+    </dependency>
+    <dependency name="ncurses">
+        <test>./make/chklib.sh ncurses</test>
+        <test>./make/chklib.sh tinfo</test>
+        <ldflags>-lncurses -ltinfo</ldflags>
+    </dependency>
+    <dependency name="ncurses">
+        <test>./make/chklib.sh ncurses</test>
+        <ldflags>-lncurses</ldflags>
+    </dependency>
+
     <dependency name="asan" toolchain="gnuc">
         <cflags>-fsanitize=address</cflags>
         <ldflags>-fsanitize=address</ldflags>
     </dependency>
     <target>
-        <dependencies>ncurses</dependencies>
+        <option arg="curses">
+            <desc>The curses implementation to use.</desc>
+            <value str="ncursesw">
+                <dependencies>ncursesw</dependencies>
+            </value>
+            <value str="cursesw">
+                <dependencies>cursesw</dependencies>
+            </value>
+            <value str="ncurses">
+                <dependencies>ncurses</dependencies>
+                <define name="DISABLE_UNICODE"/>
+            </value>
+            <value str="curses">
+                <dependencies>curses</dependencies>
+                <define name="DISABLE_UNICODE"/>
+            </value>
+            <default value="ncursesw"/>
+            <default value="cursesw"/>
+            <default value="ncurses"/>
+            <default value="curses"/>
+        </option>
         <feature name="asan">
             <desc>address sanitizer</desc>
             <dependencies>asan</dependencies>
--- a/src/input.h	Tue Aug 25 22:25:33 2026 +0200
+++ b/src/input.h	Mon Aug 31 15:49:31 2026 +0200
@@ -31,7 +31,7 @@
 #define	INPUT_H
 
 #include <stdlib.h>
-#include <ncurses.h>
+#include <curses.h>
 
 #ifdef	__cplusplus
 extern "C" {
--- a/src/main.c	Tue Aug 25 22:25:33 2026 +0200
+++ b/src/main.c	Mon Aug 31 15:49:31 2026 +0200
@@ -42,6 +42,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <curses.h>
 
 typedef struct {
     /**
@@ -70,7 +71,9 @@
     memset(&settings, 0, sizeof(settings));
     settings.servercolor = WHITE;
     settings.port = 27015;
+#ifndef DISABLE_UNICODE
     settings.unicode = !!setlocale(LC_CTYPE, "C.UTF-8");
+#endif
 }
 
 static void cleanup() {
@@ -184,7 +187,9 @@
 "  -h            This help page\n"
 "  -p            TCP port to use (default: 27015)\n"
 "  -u            Use Unix domain socket instead of TCP\n"
+#ifndef DISABLE_UNICODE
 "  -U            Disables unicode pieces\n"
+#endif
 "  -v            Print version information and exits\n"
 "\nTime control (default: disabled)\n"
 "  -t <time>     Time limit in minutes (or seconds when used with 's' suffix)\n"
--- a/test/Makefile	Tue Aug 25 22:25:33 2026 +0200
+++ b/test/Makefile	Mon Aug 31 15:49:31 2026 +0200
@@ -53,7 +53,44 @@
 	$(CC) -o $@ $(CFLAGS) -c $<
 
 $(BUILDDIR)/test-real-pgn.o: test-real-pgn.c ucxtest.h ../src/chess/pgn.h \
- ../src/chess/rules.h
+ ../src/chess/rules.h data/game001.pgn data/game002.pgn data/game003.pgn \
+ data/game004.pgn data/game005.pgn data/game006.pgn data/game007.pgn \
+ data/game008.pgn data/game009.pgn data/game010.pgn data/game011.pgn \
+ data/game012.pgn data/game013.pgn data/game014.pgn data/game015.pgn \
+ data/game016.pgn data/game017.pgn data/game018.pgn data/game019.pgn \
+ data/game020.pgn data/game021.pgn data/game022.pgn data/game023.pgn \
+ data/game024.pgn data/game025.pgn data/game026.pgn data/game027.pgn \
+ data/game028.pgn data/game029.pgn data/game030.pgn data/game031.pgn \
+ data/game032.pgn data/game033.pgn data/game034.pgn data/game035.pgn \
+ data/game036.pgn data/game037.pgn data/game038.pgn data/game039.pgn \
+ data/game040.pgn data/game041.pgn data/game042.pgn data/game043.pgn \
+ data/game044.pgn data/game045.pgn data/game046.pgn data/game047.pgn \
+ data/game048.pgn data/game049.pgn data/game050.pgn data/game051.pgn \
+ data/game052.pgn data/game053.pgn data/game054.pgn data/game055.pgn \
+ data/game056.pgn data/game057.pgn data/game058.pgn data/game059.pgn \
+ data/game060.pgn data/game061.pgn data/game062.pgn data/game063.pgn \
+ data/game064.pgn data/game065.pgn data/game066.pgn data/game067.pgn \
+ data/game068.pgn data/game069.pgn data/game070.pgn data/game071.pgn \
+ data/game072.pgn data/game073.pgn data/game074.pgn data/game075.pgn \
+ data/game076.pgn data/game077.pgn data/game078.pgn data/game079.pgn \
+ data/game080.pgn data/game081.pgn data/game082.pgn data/game083.pgn \
+ data/game084.pgn data/game085.pgn data/game086.pgn data/game087.pgn \
+ data/game088.pgn data/game089.pgn data/game090.pgn data/game091.pgn \
+ data/game092.pgn data/game093.pgn data/game094.pgn data/game095.pgn \
+ data/game096.pgn data/game097.pgn data/game098.pgn data/game099.pgn \
+ data/game100.pgn data/game101.pgn data/game102.pgn data/game103.pgn \
+ data/game104.pgn data/game105.pgn data/game106.pgn data/game107.pgn \
+ data/game108.pgn data/game109.pgn data/game110.pgn data/game111.pgn \
+ data/game112.pgn data/game113.pgn data/game114.pgn data/game115.pgn \
+ data/game116.pgn data/game117.pgn data/game118.pgn data/game119.pgn \
+ data/game120.pgn data/game121.pgn data/game122.pgn data/game123.pgn \
+ data/game124.pgn data/game125.pgn data/game126.pgn data/game127.pgn \
+ data/game128.pgn data/game129.pgn data/game130.pgn data/game131.pgn \
+ data/game132.pgn data/game133.pgn data/game134.pgn data/game135.pgn \
+ data/game136.pgn data/game137.pgn data/game138.pgn data/game139.pgn \
+ data/game140.pgn data/game141.pgn data/game142.pgn data/game143.pgn \
+ data/game144.pgn data/game145.pgn data/game146.pgn data/game147.pgn \
+ data/game148.pgn data/game149.pgn data/game150.pgn
 	@echo "Compiling $<"
 	$(CC) -o $@ $(CFLAGS) -c $<
 

mercurial