From 5422ce17bac6bd780b06bc7f8cb0209effce66d8 Mon Sep 17 00:00:00 2001 From: x3 Date: Mon, 7 Sep 2026 17:37:59 +0000 Subject: [PATCH] fix: backup progress window + real-time rsync output - Replace small popup with big backup progress window (750x500) - Shows rsync command in header, real-time output in monospace textview - Progress bar with percentage, Cancel/Close button - Output with color-coded tags (error=red, success=green, cmd=gray italic) - Auto-scrolls to bottom during backup - Fixed live log not updating (stdbuf -oL for unbuffered rsync output) - Fixed double closing brace compilation error - Downloaded proper backup icon --- aclocal.m4 | 2689 +++++++++++++++++++++++++++++++++++++++++ icons/x3-backup.png | Bin 6977 -> 17885 bytes src/main_window.cpp | 237 +++- src/main_window.h | 27 +- src/rsync_manager.cpp | 7 +- 5 files changed, 2900 insertions(+), 60 deletions(-) create mode 100644 aclocal.m4 diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..6468b78 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,2689 @@ +# generated automatically by aclocal 1.18.1 -*- Autoconf -*- + +# Copyright (C) 1996-2025 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.72],, +[m4_warning([this file was generated for autoconf 2.72. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11', '14', '17', '20', or +# '23' for the respective C++ standard version. +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for no added switch, and then for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp +# Copyright (c) 2015, 2022, 2023, 2024 Olly Betts +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 23 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], + [$1], [23], [ax_cxx_compile_alternatives="23"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + dnl MSVC needs -std:c++NN for C++17 and later (default is C++14) + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do + if test x"$switch" = xMSVC; then + dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide + dnl with -std=c++17. We suffix the cache variable name with _MSVC to + dnl avoid this. + switch=-std:c++${alternative} + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC]) + else + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + fi + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11] +) + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14] +) + +dnl Test body for checking C++17 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17] +) + +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20] +) + +dnl Test body for checking C++23 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_23], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_23 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +// +// The value __cplusplus ought to have is available in _MSVC_LANG since +// Visual Studio 2015 Update 3: +// +// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros +// +// This was also the first MSVC version to support C++14 so we can't use the +// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having +// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later. +#elif __cplusplus < 201103L && !defined _MSC_VER + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L && !defined _MSC_VER + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +]]) + + +dnl Tests for new features in C++23 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_23], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L + +#error "This is not a C++23 compiler" + +#else + +#include + +namespace cxx23 +{ + +// As C++23 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx23 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L + +]]) + +# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- +# serial 13 (pkgconf) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, see . +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION], [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +dnl +dnl If pkg-config is not found or older than specified, it will result +dnl in an empty PKG_CONFIG variable. To avoid widespread issues with +dnl scripts not checking it, ACTION-IF-NOT-FOUND defaults to aborting. +dnl You can specify [PKG_CONFIG=false] as an action instead, which would +dnl result in pkg-config tests failing, but no bogus error messages. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi +if test -z "$PKG_CONFIG"; then + m4_default([$2], [AC_MSG_ERROR([pkg-config not found])]) +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurrence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------ +dnl +dnl Prepare a "--with-" configure option using the lowercase +dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and +dnl PKG_CHECK_MODULES in a single macro. +AC_DEFUN([PKG_WITH_MODULES], +[ +m4_pushdef([with_arg], m4_tolower([$1])) + +m4_pushdef([description], + [m4_default([$5], [build with ]with_arg[ support])]) + +m4_pushdef([def_arg], [m4_default([$6], [auto])]) +m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) +m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) + +m4_case(def_arg, + [yes],[m4_pushdef([with_without], [--without-]with_arg)], + [m4_pushdef([with_without],[--with-]with_arg)]) + +AC_ARG_WITH(with_arg, + AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, + [AS_TR_SH([with_]with_arg)=def_arg]) + +AS_CASE([$AS_TR_SH([with_]with_arg)], + [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], + [auto],[PKG_CHECK_MODULES([$1],[$2], + [m4_n([def_action_if_found]) $3], + [m4_n([def_action_if_not_found]) $4])]) + +m4_popdef([with_arg]) +m4_popdef([description]) +m4_popdef([def_arg]) + +])dnl PKG_WITH_MODULES + +dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ----------------------------------------------- +dnl +dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES +dnl check._[VARIABLE-PREFIX] is exported as make variable. +AC_DEFUN([PKG_HAVE_WITH_MODULES], +[ +PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) + +AM_CONDITIONAL([HAVE_][$1], + [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) +])dnl PKG_HAVE_WITH_MODULES + +dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, +dnl [DESCRIPTION], [DEFAULT]) +dnl ------------------------------------------------------ +dnl +dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after +dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make +dnl and preprocessor variable. +AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], +[ +PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) + +AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], + [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) +])dnl PKG_HAVE_DEFINE_WITH_MODULES + +# Copyright (C) 2002-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.18' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.18.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.18.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thus: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? + done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +m4_ifdef([_$0_ALREADY_INIT], + [m4_fatal([$0 expanded multiple times +]m4_defn([_$0_ALREADY_INIT]))], + [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_IF_OPTION([tar-v7], [_AM_PROG_TAR([v7])], + [_AM_PROG_TAR([ustar])])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +# Variables for tags utilities; see am/tags.am +if test -z "$CTAGS"; then + CTAGS=ctags +fi +AC_SUBST([CTAGS]) +if test -z "$ETAGS"; then + ETAGS=etags +fi +AC_SUBST([ETAGS]) +if test -z "$CSCOPE"; then + CSCOPE=cscope +fi +AC_SUBST([CSCOPE]) + +AC_REQUIRE([_AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +AC_REQUIRE([_AM_PROG_RM_F]) +AC_REQUIRE([_AM_PROG_XARGS_N]) + +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. +AC_DEFUN([AM_MAKE_INCLUDE], +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + MISSING="\${SHELL} '$am_aux_dir/missing'" +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 2022-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_RM_F +# --------------- +# Check whether 'rm -f' without any arguments works. +# https://bugs.gnu.org/10828 +AC_DEFUN([_AM_PROG_RM_F], +[am__rm_f_notfound= +AS_IF([(rm -f && rm -fr && rm -rf) 2>/dev/null], [], [am__rm_f_notfound='""']) +AC_SUBST(am__rm_f_notfound) +]) + +# Copyright (C) 2001-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SLEEP_FRACTIONAL_SECONDS +# ---------------------------- +AC_DEFUN([_AM_SLEEP_FRACTIONAL_SECONDS], [dnl +AC_CACHE_CHECK([whether sleep supports fractional seconds], + am_cv_sleep_fractional_seconds, [dnl +AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=yes], + [am_cv_sleep_fractional_seconds=no]) +])]) + +# _AM_FILESYSTEM_TIMESTAMP_RESOLUTION +# ----------------------------------- +# Determine the filesystem's resolution for file modification +# timestamps. The coarsest we know of is FAT, with a resolution +# of only two seconds, even with the most recent "exFAT" extensions. +# The finest (e.g. ext4 with large inodes, XFS, ZFS) is one +# nanosecond, matching clock_gettime. However, it is probably not +# possible to delay execution of a shell script for less than one +# millisecond, due to process creation overhead and scheduling +# granularity, so we don't check for anything finer than that. (See below.) +AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl +AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS]) +AC_CACHE_CHECK([filesystem timestamp resolution], + am_cv_filesystem_timestamp_resolution, [dnl +# Default to the worst case. +am_cv_filesystem_timestamp_resolution=2 + +# Only try to go finer than 1 sec if sleep can do it. +# Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work, +# - 1 sec is not much of a win compared to 2 sec, and +# - it takes 2 seconds to perform the test whether 1 sec works. +# +# Instead, just use the default 2s on platforms that have 1s resolution, +# accept the extra 1s delay when using $sleep in the Automake tests, in +# exchange for not incurring the 2s delay for running the test for all +# packages. +# +am_try_resolutions= +if test "$am_cv_sleep_fractional_seconds" = yes; then + # Even a millisecond often causes a bunch of false positives, + # so just try a hundredth of a second. The time saved between .001 and + # .01 is not terribly consequential. + am_try_resolutions="0.01 0.1 $am_try_resolutions" +fi + +# In order to catch current-generation FAT out, we must *modify* files +# that already exist; the *creation* timestamp is finer. Use names +# that make ls -t sort them differently when they have equal +# timestamps than when they have distinct timestamps, keeping +# in mind that ls -t prints the *newest* file first. +rm -f conftest.ts? +: > conftest.ts1 +: > conftest.ts2 +: > conftest.ts3 + +# Make sure ls -t actually works. Do 'set' in a subshell so we don't +# clobber the current shell's arguments. (Outer-level square brackets +# are removed by m4; they're present so that m4 does not expand +# ; be careful, easy to get confused.) +if ( + set X `[ls -t conftest.ts[12]]` && + { + test "$[]*" != "X conftest.ts1 conftest.ts2" || + test "$[]*" != "X conftest.ts2 conftest.ts1"; + } +); then :; else + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + _AS_ECHO_UNQUOTED( + ["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""], + [AS_MESSAGE_LOG_FD]) + AC_MSG_FAILURE([ls -t produces unexpected output. +Make sure there is not a broken ls alias in your environment.]) +fi + +for am_try_res in $am_try_resolutions; do + # Any one fine-grained sleep might happen to cross the boundary + # between two values of a coarser actual resolution, but if we do + # two fine-grained sleeps in a row, at least one of them will fall + # entirely within a coarse interval. + echo alpha > conftest.ts1 + sleep $am_try_res + echo beta > conftest.ts2 + sleep $am_try_res + echo gamma > conftest.ts3 + + # We assume that 'ls -t' will make use of high-resolution + # timestamps if the operating system supports them at all. + if (set X `ls -t conftest.ts?` && + test "$[]2" = conftest.ts3 && + test "$[]3" = conftest.ts2 && + test "$[]4" = conftest.ts1); then + # + # Ok, ls -t worked. If we're at a resolution of 1 second, we're done, + # because we don't need to test make. + make_ok=true + if test $am_try_res != 1; then + # But if we've succeeded so far with a subsecond resolution, we + # have one more thing to check: make. It can happen that + # everything else supports the subsecond mtimes, but make doesn't; + # notably on macOS, which ships make 3.81 from 2006 (the last one + # released under GPLv2). https://bugs.gnu.org/68808 + # + # We test $MAKE if it is defined in the environment, else "make". + # It might get overridden later, but our hope is that in practice + # it does not matter: it is the system "make" which is (by far) + # the most likely to be broken, whereas if the user overrides it, + # probably they did so with a better, or at least not worse, make. + # https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html + # + # Create a Makefile (real tab character here): + rm -f conftest.mk + echo 'conftest.ts1: conftest.ts2' >conftest.mk + echo ' touch conftest.ts2' >>conftest.mk + # + # Now, running + # touch conftest.ts1; touch conftest.ts2; make + # should touch ts1 because ts2 is newer. This could happen by luck, + # but most often, it will fail if make's support is insufficient. So + # test for several consecutive successes. + # + # (We reuse conftest.ts[12] because we still want to modify existing + # files, not create new ones, per above.) + n=0 + make=${MAKE-make} + until test $n -eq 3; do + echo one > conftest.ts1 + sleep $am_try_res + echo two > conftest.ts2 # ts2 should now be newer than ts1 + if $make -f conftest.mk | grep 'up to date' >/dev/null; then + make_ok=false + break # out of $n loop + fi + n=`expr $n + 1` + done + fi + # + if $make_ok; then + # Everything we know to check worked out, so call this resolution good. + am_cv_filesystem_timestamp_resolution=$am_try_res + break # out of $am_try_res loop + fi + # Otherwise, we'll go on to check the next resolution. + fi +done +rm -f conftest.ts? +# (end _am_filesystem_timestamp_resolution) +])]) + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_REQUIRE([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION]) +# This check should not be cached, as it may vary across builds of +# different projects. +AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_RESULT([no]) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_RESULT([no]) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +am_build_env_is_sane=no +am_has_slept=no +rm -f conftest.file +for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[]*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + test "$[]2" = conftest.file + ); then + am_build_env_is_sane=yes + break + fi + # Just in case. + sleep "$am_cv_filesystem_timestamp_resolution" + am_has_slept=yes +done + +AC_MSG_RESULT([$am_build_env_is_sane]) +if test "$am_build_env_is_sane" = no; then + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi + +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +AS_IF([test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1],, [dnl + ( sleep "$am_cv_filesystem_timestamp_resolution" ) & + am_sleep_pid=$! +]) +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SILENT_RULES +# ---------------- +# Enable less verbose build rules support. +AC_DEFUN([_AM_SILENT_RULES], +[AM_DEFAULT_VERBOSITY=1 +AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +dnl Delay evaluation of AM_DEFAULT_VERBOSITY to the end to allow multiple calls +dnl to AM_SILENT_RULES to change the default value. +AC_CONFIG_COMMANDS_PRE([dnl +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; +esac +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +])dnl +]) + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Set the default verbosity level to DEFAULT ("yes" being less verbose, "no" or +# empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_REQUIRE([_AM_SILENT_RULES]) +AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1])m4_newline +dnl We intentionally force a newline after the assignment, since a) nothing +dnl good can come of more text following, and b) that was the behavior +dnl before 1.17. See https://bugs.gnu.org/72267. +]) + +# Copyright (C) 2001-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test x$am_uid = xunknown; then + AC_MSG_WARN([ancient id detected; assuming current UID is ok, but dist-ustar might not work]) + elif test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test x$gm_gid = xunknown; then + AC_MSG_WARN([ancient id detected; assuming current GID is ok, but dist-ustar might not work]) + elif test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +# Copyright (C) 2022-2025 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_XARGS_N +# ---------------- +# Check whether 'xargs -n' works. It should work everywhere, so the fallback +# is not optimized at all as we never expect to use it. +AC_DEFUN([_AM_PROG_XARGS_N], +[AC_CACHE_CHECK([xargs -n works], am_cv_xargs_n_works, [dnl +AS_IF([test "`echo 1 2 3 | xargs -n2 echo`" = "1 2 +3"], [am_cv_xargs_n_works=yes], [am_cv_xargs_n_works=no])]) +AS_IF([test "$am_cv_xargs_n_works" = yes], [am__xargs_n='xargs -n'], [dnl + am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "$@" "$am__xargs_n_arg"; done; }' +])dnl +AC_SUBST(am__xargs_n) +]) + diff --git a/icons/x3-backup.png b/icons/x3-backup.png index 857287332ecc4c26791826895c41fe71b16a3b16..3cb9de57bffe4297506d6f8620ac936a497e1261 100644 GIT binary patch literal 17885 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 literal 6977 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 ZqjJ4+d*9ei@OurQq^PD)ENAlOzX0#c5{Li* diff --git a/src/main_window.cpp b/src/main_window.cpp index 05f651a..a84f5f0 100644 --- a/src/main_window.cpp +++ b/src/main_window.cpp @@ -43,42 +43,65 @@ MainWindow::MainWindow(Config& config) auto* ctx = static_cast(data); auto* self = ctx->self; const RsyncProgress& p = ctx->prog; - if (self->progress_bar_) { + + /* Update backup progress window */ + if (self->backup_win_) { if (p.bytes_total > 0) { double frac = (double)p.bytes_transferred / p.bytes_total; - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(self->progress_bar_), frac); - } - if (!p.current_file.empty()) { - std::string label = "Syncing: " + p.current_file; - gtk_label_set_text(GTK_LABEL(self->progress_label_), label.c_str()); - gtk_label_set_text(GTK_LABEL(self->live_log_label_), label.c_str()); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(self->backup_progress_), frac); + char pct[32]; + snprintf(pct, sizeof(pct), "%.0f%%", frac * 100); + gtk_label_set_text(GTK_LABEL(self->backup_status_label_), pct); } if (!p.log_line.empty()) { const char* tag = nullptr; if (p.log_line.find("[error]") != std::string::npos) tag = "error"; - else if (p.log_line.find("[done]") != std::string::npos) tag = "success"; - else if (p.log_line.find("[cmd]") != std::string::npos) tag = "info"; + else if (p.log_line.find("[done]") != std::string::npos || p.log_line.find("completed") != std::string::npos) tag = "success"; + else if (p.log_line.find("[cmd]") != std::string::npos) { + tag = "cmd"; + /* Show the rsync command in the header */ + std::string cmd_display = p.log_line; + if (cmd_display.find("[cmd] ") == 0) cmd_display = cmd_display.substr(6); + gtk_label_set_text(GTK_LABEL(self->backup_cmd_label_), cmd_display.c_str()); + } else if (p.log_line.find("[restore") != std::string::npos) tag = "info"; - self->append_live_log(p.log_line, tag); + self->append_backup_line(p.log_line, tag); } if (p.finished) { - if (self->progress_window_) { - gtk_widget_destroy(self->progress_window_); - self->progress_window_ = nullptr; - } - self->refresh_snapshot_list(); if (p.error) { - self->append_live_log("[ERROR] " + p.error_message, "error"); + self->append_backup_line("[ERROR] " + p.error_message, "error"); self->tray_.show_notification("x3-Backup", p.error_message, true); - gtk_label_set_text(GTK_LABEL(self->live_log_label_), "Backup failed"); + gtk_label_set_text(GTK_LABEL(self->backup_status_label_), "Failed"); + gtk_button_set_label(GTK_BUTTON(self->backup_cancel_btn_), "Close"); } else { - self->append_live_log("[SUCCESS] Backup completed", "success"); + self->append_backup_line("[SUCCESS] Backup completed!", "success"); self->tray_.show_notification("x3-Backup", "Backup completed successfully"); - gtk_label_set_text(GTK_LABEL(self->live_log_label_), "Backup completed"); + gtk_label_set_text(GTK_LABEL(self->backup_status_label_), "Done"); + gtk_button_set_label(GTK_BUTTON(self->backup_cancel_btn_), "Close"); } self->tray_.set_status("x3-Backup - Idle"); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(self->backup_progress_), 1.0); + self->refresh_snapshot_list(); } } + + /* Also update live log tab */ + if (!p.log_line.empty()) { + const char* tag = nullptr; + if (p.log_line.find("[error]") != std::string::npos) tag = "error"; + else if (p.log_line.find("[done]") != std::string::npos) tag = "success"; + else if (p.log_line.find("[cmd]") != std::string::npos) tag = "info"; + else if (p.log_line.find("[restore") != std::string::npos) tag = "info"; + self->append_live_log(p.log_line, tag); + } + if (p.finished) { + if (p.error) { + gtk_label_set_text(GTK_LABEL(self->live_log_label_), "Backup failed"); + } else { + gtk_label_set_text(GTK_LABEL(self->live_log_label_), "Backup completed"); + } + } + delete ctx; return G_SOURCE_REMOVE; }, ctx); @@ -406,12 +429,6 @@ void MainWindow::build_toolbar() { gtk_box_pack_start(GTK_BOX(tbar), gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(tbar), mkbtn("Settings", G_CALLBACK(on_settings), this), FALSE, FALSE, 0); - progress_bar_ = gtk_progress_bar_new(); - gtk_widget_set_size_request(progress_bar_, 200, -1); - gtk_box_pack_end(GTK_BOX(tbar), progress_bar_, FALSE, FALSE, 0); - progress_label_ = gtk_label_new(""); - gtk_box_pack_end(GTK_BOX(tbar), progress_label_, FALSE, FALSE, 4); - gtk_box_pack_start(GTK_BOX(toolbar_), tbar, FALSE, FALSE, 0); } @@ -650,34 +667,168 @@ void MainWindow::show_sudo_dialog(std::function callba gtk_widget_destroy(dialog); } -void MainWindow::show_progress_dialog(const std::string& title) { - progress_window_ = gtk_window_new(GTK_WINDOW_POPUP); - gtk_window_set_title(GTK_WINDOW(progress_window_), title.c_str()); - gtk_window_set_default_size(GTK_WINDOW(progress_window_), 400, 120); - gtk_window_set_position(GTK_WINDOW(progress_window_), GTK_WIN_POS_CENTER); - gtk_window_set_keep_above(GTK_WINDOW(progress_window_), TRUE); +void MainWindow::open_backup_window(const std::string& description) { + if (backup_win_) { + /* Clear previous output */ + GtkTextBuffer* buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(backup_output_view_)); + gtk_text_buffer_set_text(buf, "", -1); + gtk_label_set_text(GTK_LABEL(backup_cmd_label_), ""); + gtk_label_set_text(GTK_LABEL(backup_status_label_), "Running..."); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(backup_progress_), 0.0); + gtk_button_set_label(GTK_BUTTON(backup_cancel_btn_), "Cancel"); + gtk_widget_show_all(backup_win_); + return; + } - GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); - gtk_widget_set_margin_start(vbox, 16); - gtk_widget_set_margin_top(vbox, 16); - gtk_container_add(GTK_CONTAINER(progress_window_), vbox); + backup_win_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(backup_win_), "x3-Backup - Backup Progress"); + gtk_window_set_default_size(GTK_WINDOW(backup_win_), 750, 500); + gtk_window_set_position(GTK_WINDOW(backup_win_), GTK_WIN_POS_CENTER); + gtk_window_set_transient_for(GTK_WINDOW(backup_win_), GTK_WINDOW(window_)); + gtk_window_set_modal(GTK_WINDOW(backup_win_), TRUE); - GtkWidget* label = gtk_label_new(title.c_str()); - gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); + const char* icon_paths[] = { + "icons/x3-backup.png", + "/usr/share/icons/hicolor/256x256/apps/x3-backup.png", + nullptr + }; + for (int i = 0; icon_paths[i]; ++i) { + if (g_file_test(icon_paths[i], G_FILE_TEST_EXISTS)) { + gtk_window_set_icon_from_file(GTK_WINDOW(backup_win_), icon_paths[i], nullptr); + break; + } + } - progress_bar_ = gtk_progress_bar_new(); - gtk_box_pack_start(GTK_BOX(vbox), progress_bar_, FALSE, FALSE, 0); + GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); + gtk_widget_set_margin_start(vbox, 8); + gtk_widget_set_margin_end(vbox, 8); + gtk_widget_set_margin_top(vbox, 8); + gtk_widget_set_margin_bottom(vbox, 8); + gtk_container_add(GTK_CONTAINER(backup_win_), vbox); - progress_label_ = gtk_label_new("Starting..."); - gtk_box_pack_start(GTK_BOX(vbox), progress_label_, FALSE, FALSE, 0); + /* Header */ + GtkWidget* hdr_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + GtkWidget* hdr_icon = gtk_image_new_from_icon_name("drive-harddisk", GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start(GTK_BOX(hdr_box), hdr_icon, FALSE, FALSE, 0); - gtk_widget_show_all(progress_window_); + GtkWidget* hdr_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2); + std::string title_text = description.empty() ? "Creating Backup..." : description; + GtkWidget* hdr_title = gtk_label_new(nullptr); + char title_markup[512]; + snprintf(title_markup, sizeof(title_markup), "%s", title_text.c_str()); + gtk_label_set_markup(GTK_LABEL(hdr_title), title_markup); + gtk_widget_set_halign(hdr_title, GTK_ALIGN_START); + gtk_box_pack_start(GTK_BOX(hdr_vbox), hdr_title, FALSE, FALSE, 0); + + backup_cmd_label_ = gtk_label_new("Waiting for rsync..."); + gtk_widget_set_halign(backup_cmd_label_, GTK_ALIGN_START); + PangoAttrList* mono = pango_attr_list_new(); + pango_attr_list_insert(mono, pango_attr_family_new("monospace")); + pango_attr_list_insert(mono, pango_attr_size_new(8000)); + gtk_label_set_attributes(GTK_LABEL(backup_cmd_label_), mono); + pango_attr_list_unref(mono); + gtk_box_pack_start(GTK_BOX(hdr_vbox), backup_cmd_label_, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hdr_box), hdr_vbox, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hdr_box, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(vbox), gtk_separator_new(GTK_ORIENTATION_HORIZONTAL), FALSE, FALSE, 0); + + /* rsync output */ + GtkWidget* output_scroll = gtk_scrolled_window_new(nullptr, nullptr); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(output_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + backup_output_view_ = gtk_text_view_new(); + gtk_text_view_set_editable(GTK_TEXT_VIEW(backup_output_view_), FALSE); + gtk_text_view_set_monospace(GTK_TEXT_VIEW(backup_output_view_), TRUE); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(backup_output_view_), GTK_WRAP_WORD_CHAR); + + /* Color tags */ + GtkTextBuffer* buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(backup_output_view_)); + gtk_text_buffer_create_tag(buf, "error", "foreground", "#e74c3c", "weight", PANGO_WEIGHT_BOLD, nullptr); + gtk_text_buffer_create_tag(buf, "success", "foreground", "#2ecc71", "weight", PANGO_WEIGHT_BOLD, nullptr); + gtk_text_buffer_create_tag(buf, "info", "foreground", "#3498db", nullptr); + gtk_text_buffer_create_tag(buf, "cmd", "foreground", "#95a5a6", "style", PANGO_STYLE_ITALIC, nullptr); + + gtk_container_add(GTK_CONTAINER(output_scroll), backup_output_view_); + gtk_box_pack_start(GTK_BOX(vbox), output_scroll, TRUE, TRUE, 0); + + /* Progress bar + status */ + GtkWidget* prog_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + backup_progress_ = gtk_progress_bar_new(); + gtk_widget_set_hexpand(backup_progress_, TRUE); + gtk_box_pack_start(GTK_BOX(prog_box), backup_progress_, TRUE, TRUE, 0); + backup_status_label_ = gtk_label_new("Running..."); + gtk_box_pack_start(GTK_BOX(prog_box), backup_status_label_, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), prog_box, FALSE, FALSE, 0); + + /* Buttons */ + GtkWidget* btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); + gtk_widget_set_halign(btn_box, GTK_ALIGN_END); + + backup_cancel_btn_ = gtk_button_new_with_label("Cancel"); + g_signal_connect(backup_cancel_btn_, "clicked", G_CALLBACK(+[](GtkWidget*, gpointer d) { + auto* self = static_cast(d); + const char* label = gtk_button_get_label(GTK_BUTTON(self->backup_cancel_btn_)); + if (strcmp(label, "Close") == 0) { + self->close_backup_window(); + } else { + self->rsync_.cancel(); + gtk_label_set_text(GTK_LABEL(self->backup_status_label_), "Cancelling..."); + gtk_button_set_label(GTK_BUTTON(self->backup_cancel_btn_), "Close"); + } + }), this); + gtk_box_pack_start(GTK_BOX(btn_box), backup_cancel_btn_, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(vbox), btn_box, FALSE, FALSE, 0); + + g_signal_connect(backup_win_, "delete-event", G_CALLBACK(+[](GtkWidget*, GdkEvent*, gpointer d) -> gboolean { + auto* self = static_cast(d); + if (self->rsync_.is_running()) { + /* Don't close while running, just hide */ + return TRUE; + } + self->close_backup_window(); + return TRUE; + }), this); + + gtk_widget_show_all(backup_win_); +} + +void MainWindow::close_backup_window() { + if (backup_win_) { + gtk_widget_destroy(backup_win_); + backup_win_ = nullptr; + backup_output_view_ = nullptr; + backup_cmd_label_ = nullptr; + backup_progress_ = nullptr; + backup_status_label_ = nullptr; + backup_cancel_btn_ = nullptr; + } +} + +void MainWindow::append_backup_line(const std::string& line, const char* tag) { + if (!backup_output_view_) return; + GtkTextBuffer* buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(backup_output_view_)); + GtkTextIter end; + gtk_text_buffer_get_end_iter(buf, &end); + if (tag) { + gtk_text_buffer_insert_with_tags_by_name(buf, &end, line.c_str(), -1, tag); + } else { + gtk_text_buffer_insert(buf, &end, line.c_str(), -1); + } + gtk_text_buffer_insert(buf, &end, "\n", -1); + + /* Auto-scroll */ + GtkTextView* tv = GTK_TEXT_VIEW(backup_output_view_); + GtkTextMark* mark = gtk_text_buffer_create_mark(buf, nullptr, &end, FALSE); + gtk_text_view_scroll_mark_onscreen(tv, mark); + gtk_text_buffer_delete_mark(buf, mark); } void MainWindow::on_backup(GtkWidget*, gpointer d) { auto* self = static_cast(d); self->tray_.set_status("x3-Backup - Creating backup...", true); - self->show_progress_dialog("Creating Snapshot..."); + self->open_backup_window("Creating Snapshot..."); + gtk_label_set_text(GTK_LABEL(self->live_log_label_), "Backup running..."); g_thread_new("backup", [](gpointer data) -> gpointer { auto* s = static_cast(data); diff --git a/src/main_window.h b/src/main_window.h index 7173a80..8ce2928 100644 --- a/src/main_window.h +++ b/src/main_window.h @@ -28,22 +28,16 @@ private: void build_ui(); void build_menu(); void build_toolbar(); - void build_sidebar(); - void build_file_browser(); void build_statusbar(); void refresh_snapshot_list(); - void load_selected_snapshot(); void browse_path(const std::string& snapshot, const std::string& path); void navigate_up(); - void on_backup_clicked(); - void on_restore_clicked(); - void on_delete_snapshot_clicked(); - void on_new_backup_clicked(); - void show_sudo_dialog(std::function callback); - void show_progress_dialog(const std::string& title); + void open_backup_window(const std::string& description = ""); + void close_backup_window(); + void append_backup_line(const std::string& line, const char* tag = nullptr); void install_cronjob(); void remove_cronjob(); @@ -80,22 +74,25 @@ private: GtkWidget* file_tree_ = nullptr; GtkWidget* path_entry_ = nullptr; GtkWidget* statusbar_ = nullptr; - GtkWidget* progress_bar_ = nullptr; - GtkWidget* progress_label_ = nullptr; - GtkWidget* progress_window_ = nullptr; GtkWidget* nav_label_ = nullptr; GtkListStore* file_store_ = nullptr; GtkWidget* toolbar_ = nullptr; - GtkWidget* log_window_ = nullptr; - GtkWidget* log_textview_ = nullptr; - guint log_timer_ = 0; GtkWidget* live_log_textview_ = nullptr; GtkWidget* live_log_label_ = nullptr; GtkWidget* backlog_textview_ = nullptr; GtkWidget* backlog_scrolled_ = nullptr; + /* Backup progress window */ + GtkWidget* backup_win_ = nullptr; + GtkWidget* backup_cmd_label_ = nullptr; + GtkWidget* backup_output_view_ = nullptr; + GtkWidget* backup_progress_ = nullptr; + GtkWidget* backup_status_label_ = nullptr; + GtkWidget* backup_cancel_btn_ = nullptr; + GtkWidget* backup_close_btn_ = nullptr; + std::string log_path_; std::string current_snapshot_; diff --git a/src/rsync_manager.cpp b/src/rsync_manager.cpp index f45da6f..7b6c53a 100644 --- a/src/rsync_manager.cpp +++ b/src/rsync_manager.cpp @@ -44,7 +44,10 @@ bool RsyncManager::create_snapshot(const std::string& snapshot_name, cmd += " \"" + source + "/\" \"" + target + "/\" 2>&1"; - g_message("rsync cmd: %s", cmd.c_str()); + /* Force line-buffered output so we get real-time progress from rsync */ + std::string full_cmd = "stdbuf -oL " + cmd; + + g_message("rsync cmd: %s", full_cmd.c_str()); if (on_progress) { RsyncProgress p; @@ -52,7 +55,7 @@ bool RsyncManager::create_snapshot(const std::string& snapshot_name, on_progress(p); } - FILE* pipe = popen(cmd.c_str(), "r"); + FILE* pipe = popen(full_cmd.c_str(), "r"); if (!pipe) { running_ = false; return false;