From 6bca9aedd658bfaef2cf2c348fed211640912c2c Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sat, 3 Aug 2024 10:56:31 +0200 Subject: [PATCH 1/7] Do not install system wxWidgets targets --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 580cc106..07c7b6a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,7 +287,10 @@ if(BUILD_QSPGUI) target_compile_options(qspgui PRIVATE ${PROJECT_COMPILER_FLAGS}) target_link_options(qspgui PRIVATE ${PROJECT_LINKER_FLAGS}) target_link_libraries(qspgui PRIVATE qsp fmod wxbase wxcore wxadv wxaui wxhtml) - install(TARGETS qspgui qsp wxbase wxcore wxadv wxaui wxhtml) + install(TARGETS qspgui qsp) + if (NOT USE_INSTALLED_WX) + install(TARGETS wxbase wxcore wxadv wxaui wxhtml) + endif() install(DIRECTORY "${CMAKE_SOURCE_DIR}/players/classic/misc/common/langs" DESTINATION "${RESOURCES_DIR}") install(DIRECTORY "${CMAKE_SOURCE_DIR}/players/classic/misc/common/sound" DESTINATION "${RESOURCES_DIR}") From dcc81587b5efcf2c139f8c61a79db3d8ad9de1bc Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sat, 17 Aug 2024 09:21:07 +0200 Subject: [PATCH 2/7] Add headers to target sources So that IDEs can list them. --- CMakeLists.txt | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07c7b6a2..fa621069 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,30 +84,33 @@ endif() configure_file(qsp_config.h.cmakein qsp_config.h @ONLY) set(QSP_SOURCES + qsp/bindings/bindings_config.h qsp/bindings/default/default_callbacks.c qsp/bindings/default/default_control.c - qsp/actions.c - qsp/callbacks.c - qsp/codetools.c - qsp/coding.c - qsp/common.c - qsp/errors.c - qsp/game.c - qsp/locations.c - qsp/mathops.c - qsp/memwatch.c - qsp/menu.c - qsp/objects.c - qsp/playlist.c - qsp/regexp.c - qsp/statements.c - qsp/text.c - qsp/time.c + qsp/bindings/default/qsp_default.h + qsp/bindings/qsp.h + qsp/actions.c qsp/actions.h + qsp/callbacks.c qsp/callbacks.h + qsp/codetools.c qsp/codetools.h + qsp/coding.c qsp/coding.h + qsp/common.c qsp/common.h + qsp/errors.c qsp/errors.h + qsp/game.c qsp/game.h + qsp/locations.c qsp/locations.h + qsp/mathops.c qsp/mathops.h + qsp/memwatch.c qsp/memwatch.h + qsp/menu.c qsp/menu.h + qsp/objects.c qsp/objects.h + qsp/playlist.c qsp/playlist.h + qsp/regexp.c qsp/regexp.h + qsp/statements.c qsp/statements.h + qsp/text.c qsp/text.h + qsp/time.c qsp/time.h qsp/towlower.c qsp/towupper.c - qsp/tuples.c - qsp/variables.c - qsp/variant.c + qsp/tuples.c qsp/tuples.h + qsp/variables.c qsp/variables.h + qsp/variant.c qsp/variant.h ) add_library(qsp SHARED ${QSP_SOURCES}) target_compile_definitions(qsp PUBLIC _UNICODE) From 35cdb702edf5be9f91ae342b808f5ee8224b15e5 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sat, 17 Aug 2024 09:33:00 +0200 Subject: [PATCH 3/7] Tune up finding/installing oniguruma Simplify script, fix install() for the bundled onigiruma, fix using pkg-config in the find module. --- CMakeLists.txt | 11 +++++------ cmake/Modules/Findoniguruma.cmake | 5 +++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa621069..6bf62969 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ else() add_subdirectory("${CMAKE_BINARY_DIR}/oniguruma-src" "${CMAKE_BINARY_DIR}/oniguruma-build" ) + add_library(oniguruma::onig ALIAS onig) endif() configure_file(qsp_config.h.cmakein qsp_config.h @ONLY) @@ -119,12 +120,7 @@ if(WIN32) endif() target_compile_options(qsp PRIVATE ${PROJECT_COMPILER_FLAGS}) target_link_options(qsp PRIVATE ${PROJECT_LINKER_FLAGS}) -if(USE_INSTALLED_ONIGURUMA) - target_link_libraries(qsp PRIVATE oniguruma::onig) -else() - target_link_libraries(qsp PRIVATE onig) - install(TARGETS onig) -endif() +target_link_libraries(qsp PRIVATE oniguruma::onig) target_include_directories(qsp INTERFACE @@ -133,6 +129,9 @@ target_include_directories(qsp ) install(TARGETS qsp EXPORT QspTargets DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime) +if(NOT USE_INSTALLED_ONIGURUMA) + install(TARGETS onig DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime) +endif() generate_export_header(qsp BASE_NAME Qsp diff --git a/cmake/Modules/Findoniguruma.cmake b/cmake/Modules/Findoniguruma.cmake index 60262440..70826c04 100644 --- a/cmake/Modules/Findoniguruma.cmake +++ b/cmake/Modules/Findoniguruma.cmake @@ -3,7 +3,7 @@ # Redistribution and use is allowed according to the terms of the BSD license. if (NOT TARGET oniguruma::onig) - find_package(oniguruma CONFIG) + find_package(oniguruma CONFIG QUIET) if (TARGET onig) add_library(oniguruma::onig ALIAS onig) set(oniguruma_FOUND True) @@ -11,7 +11,8 @@ if (NOT TARGET oniguruma::onig) include(FindPackageHandleStandardArgs) if (NOT WIN32) # use pkg-config to get the directories and then use these values - include(FindPkgConfig) + include(CMakeFindDependencyMacro) + find_dependency(PkgConfig) message(VERBOSE "FindOnigurama: trying pkg-config") pkg_check_modules(oniguruma REQUIRED IMPORTED_TARGET GLOBAL oniguruma) add_library(oniguruma::onig ALIAS PkgConfig::oniguruma) From f7ed212815229adeffd579cfb823ec6ad98bd2fc Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sat, 17 Aug 2024 10:40:35 +0200 Subject: [PATCH 4/7] Add build tree cmake export This allows to use find_package() with the build tree. --- CMakeLists.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bf62969..8fe3a1fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,8 @@ target_link_libraries(qsp PRIVATE oniguruma::onig) target_include_directories(qsp INTERFACE + "$" + "$" "$" "$" ) @@ -138,17 +140,17 @@ generate_export_header(qsp EXPORT_MACRO_NAME QSP_EXTERN ) -write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/QspConfigVersion.cmake COMPATIBILITY AnyNewerVersion) -configure_package_config_file(QspConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/QspConfig.cmake +write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/cmake/Qsp/QspConfigVersion.cmake COMPATIBILITY AnyNewerVersion) +configure_package_config_file(QspConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cmake/Qsp/QspConfig.cmake INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Qsp" ) +export(TARGETS qsp NAMESPACE Qsp:: FILE ${CMAKE_CURRENT_BINARY_DIR}/QspConfig.cmake) install(EXPORT QspTargets NAMESPACE Qsp:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Qsp") -install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/QspConfigVersion.cmake - ${CMAKE_CURRENT_BINARY_DIR}/QspConfig.cmake - DESTINATION - "${CMAKE_INSTALL_LIBDIR}/cmake/Qsp" + +install( + DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/cmake + DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) install(FILES From b9261f9d845435b2e790cf00a896bc7fd920920a Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sat, 17 Aug 2024 13:35:27 +0200 Subject: [PATCH 5/7] Add missing include --- qsp/bindings/default/qsp_default.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qsp/bindings/default/qsp_default.h b/qsp/bindings/default/qsp_default.h index 706920bb..b1d1735e 100644 --- a/qsp/bindings/default/qsp_default.h +++ b/qsp/bindings/default/qsp_default.h @@ -15,6 +15,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifdef _UNICODE +#include +#endif + #ifndef QSP_DEFAULTDEFINES #define QSP_DEFAULTDEFINES From f8fce6c5b892a44f7498c014a1647f6483fe9c43 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sat, 17 Aug 2024 22:18:27 +0200 Subject: [PATCH 6/7] Move the endianness test to the build script --- CMakeLists.txt | 10 +++++++++- qsp/bindings/default/qsp_default.h | 20 ++++++++++++-------- qsp_config.h.cmakein | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fe3a1fc..116e7b7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15 FATAL_ERROR) +cmake_minimum_required(VERSION 3.20 FATAL_ERROR) project(qsp VERSION 5.9.0) set(QSP_GAMEMIN_VER "5.9.0") @@ -82,6 +82,14 @@ else() add_library(oniguruma::onig ALIAS onig) endif() +if (CMAKE_C_BYTE_ORDER STREQUAL "LITTLE_ENDIAN") + set(QSP_LITTLE_ENDIAN 1) +elseif (CMAKE_C_BYTE_ORDER STREQUAL "BIG_ENDIAN") + set(QSP_LITTLE_ENDIAN 0) +else() + message(FATAL_ERROR "Could not recognize endianess: ${CMAKE_C_BYTE_ORDER}") +endif() + configure_file(qsp_config.h.cmakein qsp_config.h @ONLY) set(QSP_SOURCES diff --git a/qsp/bindings/default/qsp_default.h b/qsp/bindings/default/qsp_default.h index b1d1735e..1e3e38b2 100644 --- a/qsp/bindings/default/qsp_default.h +++ b/qsp/bindings/default/qsp_default.h @@ -15,6 +15,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "qsp_config.h" + #ifdef _UNICODE #include #endif @@ -22,16 +24,16 @@ #ifndef QSP_DEFAULTDEFINES #define QSP_DEFAULTDEFINES - static int qspEndiannessTestValue = 1; - #ifdef _UNICODE typedef wchar_t QSP_CHAR; #define QSP_FMT2(x) L##x #define QSP_FMT(x) QSP_FMT2(x) - #define QSP_ONIG_ENC ((*(char *)&(qspEndiannessTestValue) == 1) ? \ - (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_LE : ONIG_ENCODING_UTF32_LE) : \ - (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_BE : ONIG_ENCODING_UTF32_BE)) + #if QSP_LITTLE_ENDIAN + #define QSP_ONIG_ENC (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_LE : ONIG_ENCODING_UTF32_LE) + #else + #define QSP_ONIG_ENC (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_BE : ONIG_ENCODING_UTF32_BE) + #endif #define QSP_FROM_OS_CHAR(a) qspReverseConvertUC(a, qspCP1251ToUnicodeTable) #define QSP_TO_OS_CHAR(a) qspDirectConvertUC(a, qspCP1251ToUnicodeTable) #define QSP_CHRLWR qspToWLower @@ -61,9 +63,11 @@ #endif #endif - #define QSP_FIXBYTESORDER(a) ((*(char *)&(qspEndiannessTestValue) == 1) ? \ - (a) : \ - ((unsigned short)(((a) << 8) | ((a) >> 8)))) + #if QSP_LITTLE_ENDIAN + #define QSP_FIXBYTESORDER(a) (a) + #else + #define QSP_FIXBYTESORDER(a) ((unsigned short)(((a) << 8) | ((a) >> 8)))) + #endif #if defined(_MSC_VER) #define QSP_TIME _time64 #else diff --git a/qsp_config.h.cmakein b/qsp_config.h.cmakein index a3ef0c55..73fc40fe 100644 --- a/qsp_config.h.cmakein +++ b/qsp_config.h.cmakein @@ -3,6 +3,6 @@ #define QSP_VER_STR "@qsp_VERSION@" #define QSP_GAMEMINVER_VER_STR "@QSP_GAMEMIN_VER@" +#define QSP_LITTLE_ENDIAN @QSP_LITTLE_ENDIAN@ #endif - From 78559314b4428c0d8668765a9afc68e5f2e6f90f Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Wed, 28 Aug 2024 08:16:35 +0200 Subject: [PATCH 7/7] Use UTF-8 for Linux The wchar_t in Linux is very wide, 32 bits, and thus almost unused, which, in turn, results in poor support in tooling. And that's to be expected when UTF-8 is the default. At the same time, Iconv, which is part of glibc, is universally available. Thus we can use it to convert UCS-2 into UTF-8 in Linux and always use UTF-8 in the library API. --- CMakeLists.txt | 7 +++ qsp/bindings/default/qsp_default.h | 38 ++++++++----- qsp/coding.c | 87 ++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 116e7b7d..130ad5d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,10 @@ elseif(APPLE OR NOT UNIX) message(FATAL_ERROR "Only Windows and Linux targets are supported") endif() +if (LINUX) + find_package(Iconv REQUIRED) +endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) set(CMAKE_INCLUDE_CURRENT_DIR True) @@ -129,6 +133,9 @@ endif() target_compile_options(qsp PRIVATE ${PROJECT_COMPILER_FLAGS}) target_link_options(qsp PRIVATE ${PROJECT_LINKER_FLAGS}) target_link_libraries(qsp PRIVATE oniguruma::onig) +if(LINUX) + target_link_libraries(qsp PRIVATE Iconv::Iconv) +endif() target_include_directories(qsp INTERFACE diff --git a/qsp/bindings/default/qsp_default.h b/qsp/bindings/default/qsp_default.h index 1e3e38b2..ddc1b8f3 100644 --- a/qsp/bindings/default/qsp_default.h +++ b/qsp/bindings/default/qsp_default.h @@ -17,29 +17,39 @@ #include "qsp_config.h" -#ifdef _UNICODE -#include +#if defined _UNICODE && !defined __linux__ + #include #endif #ifndef QSP_DEFAULTDEFINES #define QSP_DEFAULTDEFINES #ifdef _UNICODE - typedef wchar_t QSP_CHAR; - #define QSP_FMT2(x) L##x - #define QSP_FMT(x) QSP_FMT2(x) + #ifdef __linux__ + typedef char QSP_CHAR; + #define QSP_FMT(x) x - #if QSP_LITTLE_ENDIAN - #define QSP_ONIG_ENC (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_LE : ONIG_ENCODING_UTF32_LE) + #define QSP_ONIG_ENC ONIG_ENCODING_UTF8 + + #define QSP_CHRLWR tolower + #define QSP_CHRUPR toupper #else - #define QSP_ONIG_ENC (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_BE : ONIG_ENCODING_UTF32_BE) + typedef wchar_t QSP_CHAR; + #define QSP_FMT2(x) L##x + #define QSP_FMT(x) QSP_FMT2(x) + + #if QSP_LITTLE_ENDIAN + #define QSP_ONIG_ENC (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_LE : ONIG_ENCODING_UTF32_LE) + #else + #define QSP_ONIG_ENC (sizeof(QSP_CHAR) == 2 ? ONIG_ENCODING_UTF16_BE : ONIG_ENCODING_UTF32_BE) + #endif + #define QSP_FROM_OS_CHAR(a) qspReverseConvertUC(a, qspCP1251ToUnicodeTable) + #define QSP_TO_OS_CHAR(a) qspDirectConvertUC(a, qspCP1251ToUnicodeTable) + #define QSP_CHRLWR qspToWLower + #define QSP_CHRUPR qspToWUpper + #define QSP_WCTOB + #define QSP_BTOWC #endif - #define QSP_FROM_OS_CHAR(a) qspReverseConvertUC(a, qspCP1251ToUnicodeTable) - #define QSP_TO_OS_CHAR(a) qspDirectConvertUC(a, qspCP1251ToUnicodeTable) - #define QSP_CHRLWR qspToWLower - #define QSP_CHRUPR qspToWUpper - #define QSP_WCTOB - #define QSP_BTOWC #else typedef char QSP_CHAR; #define QSP_FMT(x) x diff --git a/qsp/coding.c b/qsp/coding.c index b0906c1d..6a40d8b8 100644 --- a/qsp/coding.c +++ b/qsp/coding.c @@ -19,6 +19,13 @@ #include "text.h" #include "variant.h" +#ifdef __linux__ + #include + #include + #include + #include +#endif + unsigned char qspCP1251ToKOI8RTable[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, @@ -191,6 +198,7 @@ unsigned char qspKOI8ROrderTable[] = 0x96, 0xA6, 0x97, 0x98, 0x99, 0x9A, 0x8D, 0x89, 0xA3, 0xA2, 0x8E, 0x9F, 0xA4, 0xA0, 0x9E, 0xA1 }; +#ifndef __linux__ INLINE char qspDirectConvertSB(char, unsigned char *); INLINE char qspReverseConvertSB(char, unsigned char *); INLINE int qspDirectConvertUC(char, int *); @@ -226,10 +234,65 @@ INLINE char qspReverseConvertUC(int ch, int *table) if (table[i] == ch) return (char)(i + 0x80); return 0x20; } +#else +size_t usc2StrSizeInUtf8(uint16_t *str, size_t size) +{ + size_t res = size; + uint16_t *end = str + size; + for (uint16_t *p = str; p != end; ++p) + { + if (*p > 0x7ff) + { + res += 2; + } + else if (*p > 0x7f) + { + res += 1; + } + } + return res; +} + +size_t utf8CodePointsCount(const char *str, const char *end) +{ + size_t res = 0; + for (; str != end; ++str) + res += ((*str & 0xc0) != 0x80); + return res; +} + +size_t koi8RStrSizeInUtf8(const char *data, size_t dataSize) +{ + size_t res = dataSize; + const char *end = data + dataSize; + for (; data != end; ++data) + { + if (*data < 0) + { + res += 1; + } + } + return res; +} + +#endif void *qspStringToFileData(QSPString s, QSP_BOOL isUCS2, int *dataSize) { char *buf; +#ifdef __linux__ + size_t len = qspStrLen(s); + size_t bufSize = utf8CodePointsCount(s.Str, s.End); + if (isUCS2) bufSize *= 2; + buf = (char *)malloc(bufSize); + iconv_t iconvConvDescriptor = iconv_open(isUCS2 ? "UCS−2" : "KOI8-R", "UTF−8"); + assert(iconvConvDescriptor != (iconv_t)(-1)); + char *inBuf = s.Str; + char *outBuf = buf; + size_t outBufSize = bufSize; + iconv(iconvConvDescriptor, &inBuf, &len, &outBuf, &outBufSize); + iconv_close(iconvConvDescriptor); +#else unsigned short uCh, *uPtr; QSP_CHAR *origBuf = s.Str; int bufSize, len = qspStrLen(s); @@ -249,12 +312,35 @@ void *qspStringToFileData(QSPString s, QSP_BOOL isUCS2, int *dataSize) while (--len >= 0) buf[len] = QSP_FROM_OS_CHAR(origBuf[len]); } +#endif *dataSize = bufSize; return buf; } QSPString qspStringFromFileData(void *data, int dataSize, QSP_BOOL isUCS2) { +#ifdef __linux__ + size_t inbufSize; + iconv_t iconv_cd; + size_t len, bytesLeft; + QSP_CHAR *ret; + char *inData, *outData; + + len = isUCS2 ? usc2StrSizeInUtf8(data, dataSize / 2) : koi8RStrSizeInUtf8(data, dataSize); + if (!len) return qspNullString; + ret = (QSP_CHAR *)malloc(len + 1); + errno = 0; + iconv_cd = iconv_open("UTF-8", isUCS2 ? "UCS-2" : "KOI8-R"); + assert(iconv_cd != (iconv_t)(-1)); + inbufSize = dataSize; + inData = data; + outData = ret; + bytesLeft = len; + iconv(iconv_cd, &inData, &inbufSize, &outData, &bytesLeft); + assert(bytesLeft == 0); + iconv_close(iconv_cd); + ret[len] = 0; +#else char *ptr; unsigned short uCh, *uPtr; QSP_CHAR *ret; @@ -277,6 +363,7 @@ QSPString qspStringFromFileData(void *data, int dataSize, QSP_BOOL isUCS2) while (--curLen >= 0) ret[curLen] = (QSP_CHAR)QSP_TO_OS_CHAR(ptr[curLen]); } +#endif return qspStringFromLen(ret, len); }