SDL_rtf: project: first pass conversion to SDL3

From 63ca2b60ab89ecbdb669735963318beb79200a9e Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Mon, 17 Jul 2023 17:06:53 +0200
Subject: [PATCH] project: first pass conversion to SDL3

---
 .wikiheaders-options                          |    4 +-
 CMakeLists.txt                                |  265 ++-
 Makefile.os2                                  |   86 -
 SDL2_rtf.pc.in                                |   13 -
 SDL2_rtf.spec.in                              |   66 -
 .../test-versioning.sh                        |   53 +-
 build-scripts/wikiheaders.pl                  | 1663 +++++++++++++++++
 cmake/CommonFindSDL2.cmake                    |   22 -
 cmake/FindSDL2main.cmake                      |   24 -
 cmake/PrivateSdlFunctions.cmake               |  149 +-
 .../SDL3_rtfConfig.cmake.in                   |    0
 cmake/sdl3-rtf.pc.in                          |   11 +
 cmake/sdlmanpages.cmake                       |   62 +
 examples/showrtf.c                            |   23 +-
 include/{SDL2 => SDL3}/SDL_rtf.h              |   28 +-
 sdl2_rtf-config-version.cmake.in              |   12 -
 sdl2_rtf-config.cmake.in                      |   87 -
 src/SDL_rtf.c                                 |    6 +-
 src/SDL_rtfreadr.c                            |   19 +-
 src/SDL_rtfreadr.h                            |    2 +-
 src/rtfactn.c                                 |    4 +
 src/rtfdecl.h                                 |    2 +-
 src/rtfreadr.c                                |    8 +-
 src/version.rc                                |   76 +-
 24 files changed, 2032 insertions(+), 653 deletions(-)
 delete mode 100644 Makefile.os2
 delete mode 100644 SDL2_rtf.pc.in
 delete mode 100644 SDL2_rtf.spec.in
 rename test-versioning.sh => build-scripts/test-versioning.sh (56%)
 create mode 100755 build-scripts/wikiheaders.pl
 delete mode 100644 cmake/CommonFindSDL2.cmake
 delete mode 100644 cmake/FindSDL2main.cmake
 rename SDL2_rtfConfig.cmake.in => cmake/SDL3_rtfConfig.cmake.in (100%)
 create mode 100644 cmake/sdl3-rtf.pc.in
 create mode 100644 cmake/sdlmanpages.cmake
 rename include/{SDL2 => SDL3}/SDL_rtf.h (92%)
 delete mode 100644 sdl2_rtf-config-version.cmake.in
 delete mode 100644 sdl2_rtf-config.cmake.in

diff --git a/.wikiheaders-options b/.wikiheaders-options
index fdb6c51..8269e8f 100644
--- a/.wikiheaders-options
+++ b/.wikiheaders-options
@@ -3,8 +3,8 @@ projectshortname = SDL_rtf
 incsubdir =
 wikisubdir = SDL_rtf
 apiprefixregex = RTF_
-mainincludefname = SDL2/SDL_rtf.h
-versionfname = include/SDL2/SDL_rtf.h
+mainincludefname = SDL3/SDL_rtf.h
+versionfname = include/SDL3/SDL_rtf.h
 versionmajorregex = \A\#define\s+SDL_RTF_MAJOR_VERSION\s+(\d+)\Z
 versionminorregex = \A\#define\s+SDL_RTF_MINOR_VERSION\s+(\d+)\Z
 versionpatchregex = \A\#define\s+SDL_RTF_PATCHLEVEL\s+(\d+)\Z
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 722f977..759bf99 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,259 +1,248 @@
-cmake_minimum_required(VERSION 3.14)
+cmake_minimum_required(VERSION 3.16)
 
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
 
 # See docs/release_checklist.md
-set(MAJOR_VERSION 2)
+set(MAJOR_VERSION 3)
 set(MINOR_VERSION 0)
 set(MICRO_VERSION 0)
-set(SDL_REQUIRED_VERSION 2.0.0)
+set(SDL_REQUIRED_VERSION 3.0.0)
 
-include(PrivateSdlFunctions)
-sdl_calculate_derived_version_variables()
+set(SDLTTF_REQUIRED_VERSION 3.0.0)
 
 if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
     message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL_rtf source code and call cmake from there")
 endif()
 
-project(SDL2_rtf
+project(SDL3_rtf
     LANGUAGES C
-    VERSION "${FULL_VERSION}"
+    VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}"
 )
 
+include(PrivateSdlFunctions)
+include(sdlmanpages)
+sdl_calculate_derived_version_variables(${MAJOR_VERSION} ${MINOR_VERSION} ${MICRO_VERSION})
+
 message(STATUS "Configuring ${PROJECT_NAME} ${PROJECT_VERSION}")
 
 if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
-    set(SDL2RTF_ROOTPROJECT ON)
+    set(SDL3RTF_ROOTPROJECT ON)
 else()
-    set(SDL2RTF_ROOTPROJECT OFF)
+    set(SDL3RTF_ROOTPROJECT OFF)
 endif()
 
-# Set defaults preventing destination file conflicts
-set(SDL2RTF_DEBUG_POSTFIX "d"
-    CACHE STRING "Name suffix for debug builds")
-mark_as_advanced(SDL2RTF_DEBUG_POSTFIX)
-
 # Assume MSVC projects don't have a package manager and need vendored dependencies (by default).
 # Most other platforms have some kind of package manager.
 # FIXME: consider a package manager such as conan/vcpkg instead of vendoring
-if(MSVC)
+if(ANDROID OR MSVC)
     set(vendored_default TRUE)
 else()
     set(vendored_default FALSE)
 endif()
 
+set(sdl3rtf_install_enableable ON)
+if ((TARGET SDL3-shared OR TARGET SDL3-static OR TARGET SDL3_mixer-shared OR TARGET SDL3_mixer-static) AND SDL_DISABLE_INSTALL)
+    # Cannot install SDL3_rtf when SDL3 is built in same built, and is not installed.
+    set(sdl3rtf_install_enableable OFF)
+endif()
+
+include(CMakeDependentOption)
 include(CMakePackageConfigHelpers)
 include(GNUInstallDirs)
+include(CheckSymbolExists)
 
 option(CMAKE_POSITION_INDEPENDENT_CODE "Build static libraries with -fPIC" ON)
 option(BUILD_SHARED_LIBS "Build the library as a shared library" ON)
 
+cmake_dependent_option(SDL3RTF_INSTALL "Enable SDL3_rtf install target" ${SDL3RTF_ROOTPROJECT} "${sdl3rtf_install_enableable}" OFF)
+cmake_dependent_option(SDL3RTF_INSTALL_MAN "Install man pages for SDL3_rtf" ${SDL3RTF_ROOTPROJECT} "SDL3RTF_INSTALL" OFF)
+option(SDL3RTF_WERROR "Treat warnings as errors" OFF)
+
+option(SDL3RTF_SAMPLES "Build the SDL3_rtf sample program(s)" ${SDL3RTF_ROOTPROJECT})
+cmake_dependent_option(SDL3RTF_SAMPLES_INSTALL "Install the SDL3_rtf sample program(s)" OFF "SDL3RTF_SAMPLES;SDL3RTF_INSTALL" OFF)
+
 # Save BUILD_SHARED_LIBS variable
-set(SDL2RTF_BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}")
+set(SDL3RTF_BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}")
+
+set(sdl_required_components Headers)
 
-option(SDL2RTF_SAMPLES "Build the SDL2_rtf sample program(s)" ${SDL2RTF_ROOTPROJECT})
-option(SDL2RTF_INSTALL "Enable SDL2_rtf install target" ${SDL2RTF_ROOTPROJECT})
+if(SDL3RTF_BUILD_SHARED_LIBS)
+    set(sdl3_rtf_target_name SDL3_rtf-shared)
+    set(sdl3_target_name SDL3::SDL3-shared)
 
-if(SDL2RTF_BUILD_SHARED_LIBS)
-    set(sdl2_rtf_export_name SDL2_rtf)
-    set(sdl2_rtf_install_name_infix shared)
-    set(sdl2_target_name SDL2::SDL2)
-    set(sdl2ttf_target_name SDL2_ttf::SDL2_ttf)
+    list(APPEND sdl_required_components SDL3-shared)
+
+    set(sdl3ttf_target_name SDL3_ttf::SDL3_ttf-shared)
 else()
-    set(sdl2_rtf_export_name SDL2_rtf-static)
-    set(sdl2_rtf_install_name_infix static)
-    set(sdl2_target_name SDL2::SDL2-static)
-    set(sdl2ttf_target_name SDL2_ttf::SDL2_ttf-static)
+    set(sdl3_rtf_target_name SDL3_rtf-static)
+    set(sdl3_target_name SDL3::SDL3)
+
+    set(sdl3ttf_target_name SDL3_ttf::SDL3_ttf)
+endif()
+
+if(NOT TARGET SDL3::Headers OR NOT TARGET ${sdl3_target_name})
+    find_package(SDL3 ${SDL_REQUIRED_VERSION} REQUIRED COMPONENTS ${sdl_required_components})
 endif()
 
-sdl_find_sdl2(${sdl2_target_name} ${SDL_REQUIRED_VERSION})
-if(NOT TARGET ${sdl2ttf_target_name})
-    find_package(SDL2_ttf REQUIRED)
+if(NOT TARGET ${sdl3ttf_target_name})
+    find_package(SDL3_ttf REQUIRED)
 endif()
 
-add_library(SDL2_rtf
+add_library(${sdl3_rtf_target_name}
     src/rtfactn.c
     src/rtfreadr.c
     src/SDL_rtf.c
     src/SDL_rtfreadr.c
 )
-add_library(SDL2_rtf::${sdl2_rtf_export_name} ALIAS SDL2_rtf)
-target_include_directories(SDL2_rtf PUBLIC
+add_library(SDL3_rtf::${sdl3_rtf_target_name} ALIAS ${sdl3_rtf_target_name})
+if(NOT TARGET SDL3_rtf::SDL3_rtf)
+    add_library(SDL3_rtf::SDL3_rtf ALIAS ${sdl3_rtf_target_name})
+endif()
+target_include_directories(${sdl3_rtf_target_name} PUBLIC
     "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>"
     "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
-    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/SDL2>"
+    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/SDL3>"
     "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/include>"
-    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/include/SDL2>"
+    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/include/SDL3>"
 )
-target_compile_definitions(SDL2_rtf PRIVATE
+target_compile_definitions(${sdl3_rtf_target_name} PRIVATE
     BUILD_SDL
     SDL_BUILD_MAJOR_VERSION=${MAJOR_VERSION}
     SDL_BUILD_MINOR_VERSION=${MINOR_VERSION}
     SDL_BUILD_MICRO_VERSION=${MICRO_VERSION}
 )
-target_link_libraries(SDL2_rtf PRIVATE $<BUILD_INTERFACE:${sdl2_target_name}> $<BUILD_INTERFACE:${sdl2ttf_target_name}>)
-if(WIN32 AND SDL2RTF_BUILD_SHARED_LIBS)
-    target_sources(SDL2_rtf PRIVATE
+target_link_libraries(${sdl3_rtf_target_name} PUBLIC SDL3::Headers)
+if(SDL3RTF_BUILD_SHARED_LIBS)
+    target_link_libraries(${sdl3_rtf_target_name} PRIVATE SDL3::SDL3-shared)
+endif()
+sdl_add_warning_options(${sdl3_rtf_target_name} WARNING_AS_ERROR ${SDL3RTF_WERROR})
+if(WIN32 AND SDL3RTF_BUILD_SHARED_LIBS)
+    target_sources(${sdl3_rtf_target_name} PRIVATE
         src/version.rc
     )
 endif()
-set_target_properties(SDL2_rtf PROPERTIES
+set_target_properties(${sdl3_rtf_target_name} PROPERTIES
+    OUTPUT_NAME SDL3_rtf
     DEFINE_SYMBOL DLL_EXPORT
-    EXPORT_NAME ${sdl2_rtf_export_name}
+    EXPORT_NAME ${sdl3_rtf_target_name}
     C_VISIBILITY_PRESET "hidden"
 )
 if(NOT ANDROID)
-    set_target_properties(SDL2_rtf PROPERTIES
-        DEBUG_POSTFIX "${SDL2RTF_DEBUG_POSTFIX}"
-    )
     if(APPLE)
         # the SOVERSION property corresponds to the compatibility version and VERSION corresponds to the current version
         # https://cmake.org/cmake/help/latest/prop_tgt/SOVERSION.html#mach-o-versions
-        set_target_properties(SDL2_rtf PROPERTIES
-            SOVERSION "${DYLIB_COMPATIBILITY_VERSION}"
+        set_target_properties(${sdl3_rtf_target_name} PROPERTIES
+            SOVERSION "${DYLIB_COMPAT_VERSION}"
             VERSION "${DYLIB_CURRENT_VERSION}"
         )
     else()
-        set_target_properties(SDL2_rtf PROPERTIES
-            SOVERSION "${LT_MAJOR}"
-            VERSION "${LT_VERSION}"
+        set_target_properties(${sdl3_rtf_target_name} PROPERTIES
+            SOVERSION "${SO_VERSION_MAJOR}"
+            VERSION "${SO_VERSION}"
         )
     endif()
 endif()
-if(SDL2RTF_BUILD_SHARED_LIBS AND (APPLE OR (UNIX AND NOT ANDROID)))
-    add_custom_command(TARGET SDL2_rtf POST_BUILD
-        COMMAND "${CMAKE_COMMAND}" -E create_symlink "$<TARGET_SONAME_FILE_NAME:SDL2_rtf>" "libSDL2_rtf$<$<CONFIG:Debug>:${SDL2RTF_DEBUG_POSTFIX}>$<TARGET_FILE_SUFFIX:SDL2_rtf>"
-        # BYPRODUCTS "libSDL2_rtf$<$<CONFIG:Debug>:${SDL2RTF_DEBUG_POSTFIX}>$<TARGET_FILE_SUFFIX:SDL2_rtf>" # Needs CMake 3.20
-        WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
-    )
-endif()
-if(SDL2RTF_BUILD_SHARED_LIBS)
-    if(WIN32 OR OS2)
-        set_target_properties(SDL2_rtf PROPERTIES
+if(SDL3RTF_BUILD_SHARED_LIBS)
+    if(WIN32)
+        set_target_properties(${sdl3_rtf_target_name} PROPERTIES
             PREFIX ""
         )
     endif()
-    if(OS2)
-        # OS/2 doesn't support a DLL name longer than 8 characters.
-        set_target_properties(SDL2_rtf PROPERTIES
-            OUTPUT_NAME "SDL2rtf"
-        )
-    elseif(UNIX AND NOT ANDROID)
-        set_target_properties(SDL2_rtf PROPERTIES
-            OUTPUT_NAME "SDL2_rtf-${LT_RELEASE}"
-        )
+else()
+    if(MSVC)
+        set_target_properties(${sdl3_rtf_target_name} PROPERTIES
+            OUTPUT_NAME "SDL3_rtf-static"
+            )
     endif()
 endif()
 
-if(SDL2RTF_BUILD_SHARED_LIBS)
-    # Use `Compatible Interface Properties` to ensure a shared SDL2_Rtf is linked to a shared SDL2 library
-    set_property(TARGET SDL2_rtf PROPERTY INTERFACE_SDL2_SHARED ${SDL2RTF_BUILD_SHARED_LIBS})
-    set_property(TARGET SDL2_rtf APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SDL2_SHARED)
+if(SDL3RTF_BUILD_SHARED_LIBS)
+    # Use `Compatible Interface Properties` to ensure a shared SDL3_rtf is linked to a shared SDL3 library
+    set_property(TARGET ${sdl3_rtf_target_name} PROPERTY INTERFACE_SDL3_SHARED ${SDL3RTF_BUILD_SHARED_LIBS})
+    set_property(TARGET ${sdl3_rtf_target_name} APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SDL3_SHARED)
 endif()
 
-set(INSTALL_EXTRA_TARGETS)
-set(PC_LIBS)
-set(PC_REQUIRES SDL2_ttf)
+if(SDL3RTF_BUILD_SHARED_LIBS)
+    sdl_target_link_options_no_undefined(${sdl3_rtf_target_name})
+endif()
 
-if(SDL2RTF_INSTALL)
+if(SDL3RTF_INSTALL)
     install(
-        TARGETS SDL2_rtf
-        EXPORT SDL2_rtfTargets
+        TARGETS ${sdl3_rtf_target_name}
+        EXPORT SDL3_rtfTargets
         ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT devel
         LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT library
         RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT library
     )
     install(
-        FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/SDL2/SDL_rtf.h"
-        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/SDL2" COMPONENT DEVEL
+        FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/SDL3/SDL_rtf.h"
+        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/SDL3" COMPONENT devel
     )
 
     if(WIN32 AND NOT MINGW)
         set(SDLRTF_INSTALL_CMAKEDIR_DEFAULT "cmake")
     else()
-        set(SDLRTF_INSTALL_CMAKEDIR_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2_ttf")
+        set(SDLRTF_INSTALL_CMAKEDIR_DEFAULT "${CMAKE_INSTALL_LIBDIR}/cmake/SDL3_rtf")
     endif()
-    set(SDLRTF_INSTALL_CMAKEDIR "${SDLRTF_INSTALL_CMAKEDIR_DEFAULT}" CACHE STRING "Location where to install SDL2_rtfConfig.cmake")
+    set(SDLRTF_INSTALL_CMAKEDIR "${SDLRTF_INSTALL_CMAKEDIR_DEFAULT}" CACHE STRING "Location where to install SDL3_rtfConfig.cmake")
+    set(SDLRTF_PKGCONFIG_INSTALLDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
 
-    configure_package_config_file(SDL2_rtfConfig.cmake.in SDL2_rtfConfig.cmake
+    configure_package_config_file(cmake/SDL3_rtfConfig.cmake.in SDL3_rtfConfig.cmake
         INSTALL_DESTINATION "${SDLRTF_INSTALL_CMAKEDIR}"
     )
-    write_basic_package_version_file("${PROJECT_BINARY_DIR}/SDL2_rtfConfigVersion.cmake"
-        VERSION ${FULL_VERSION}
+    write_basic_package_version_file("${PROJECT_BINARY_DIR}/SDL3_rtfConfigVersion.cmake"
         COMPATIBILITY AnyNewerVersion
     )
     install(
         FILES
-            "${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtfConfig.cmake"
-            "${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtfConfigVersion.cmake"
+            "${CMAKE_CURRENT_BINARY_DIR}/SDL3_rtfConfig.cmake"
+            "${CMAKE_CURRENT_BINARY_DIR}/SDL3_rtfConfigVersion.cmake"
         DESTINATION ${SDLRTF_INSTALL_CMAKEDIR}
         COMPONENT devel
     )
-    install(EXPORT SDL2_rtfTargets
-        FILE SDL2_rtf-${sdl2_rtf_install_name_infix}-targets.cmake
-        NAMESPACE SDL2_rtf::
+    install(EXPORT SDL3_rtfTargets
+        FILE "${sdl3_rtf_target_name}-targets.cmake"
+        NAMESPACE SDL3_rtf::
         DESTINATION "${SDLRTF_INSTALL_CMAKEDIR}"
         COMPONENT devel
     )
 
-    set(prefix "${CMAKE_INSTALL_PREFIX}")
-    set(exec_prefix "\${prefix}")
-    set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
-    set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
-    set(PACKAGE "${PROJECT_NAME}")
-    set(VERSION ${FULL_VERSION})
-    set(SDL_VERSION ${SDL_REQUIRED_VERSION})
-    string(JOIN " " PC_REQUIRES ${PC_REQUIRES})
-    string(JOIN " " PC_LIBS ${PC_LIBS})
-    configure_file("${PROJECT_SOURCE_DIR}/SDL2_rtf.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtf.pc.intermediate" @ONLY)
-    file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtf-$<CONFIG>.pc" INPUT "${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtf.pc.intermediate")
-
-    set(PC_DESTDIR)
-    if(CMAKE_SYSTEM_NAME MATCHES FreeBSD)
-        # FreeBSD uses ${PREFIX}/libdata/pkgconfig
-        set(PC_DESTDIR "libdata/pkgconfig")
-    else()
-        set(PC_DESTDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
-    endif()
-    # Always install SDL2_rtf.pc file: libraries might be different between config modes
-    install(CODE "
-        # FIXME: use file(COPY_FILE) if minimum CMake version >= 3.21
-        execute_process(COMMAND \"\${CMAKE_COMMAND}\" -E copy_if_different
-            \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtf-$<CONFIG>.pc\"
-            \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtf.pc\")
-        file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${PC_DESTDIR}\"
-            TYPE FILE
-            FILES \"${CMAKE_CURRENT_BINARY_DIR}/SDL2_rtf.pc\")" COMPONENT devel)
-
-    if(SDL2RTF_BUILD_SHARED_LIBS AND (APPLE OR (UNIX AND NOT ANDROID)))
-        install(FILES
-            "${PROJECT_BINARY_DIR}/libSDL2_rtf$<$<CONFIG:Debug>:${SDL2RTF_DEBUG_POSTFIX}>$<TARGET_FILE_SUFFIX:SDL2_rtf>"
-            DESTINATION "${CMAKE_INSTALL_LIBDIR}"
-            COMPONENT devel
-        )
-    endif()
+    file(RELATIVE_PATH SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${CMAKE_INSTALL_PREFIX}/${SDLRTF_PKGCONFIG_INSTALLDIR}" "${CMAKE_INSTALL_PREFIX}")
+    string(REGEX REPLACE "[/]+$" "" SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}")
+    set(SDL_PKGCONFIG_PREFIX "\${pcfiledir}/${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}")
+
+    configure_file(cmake/sdl3-rtf.pc.in sdl3-rtf.pc @ONLY)
+
+    # Always install sdl3-rtf.pc file: libraries might be different between config modes
+    install(FILES "${CMAKE_CURRENT_BINARY_DIR}/sdl3-rtf.pc"
+        DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT devel)
 
     install(FILES "LICENSE.txt"
         DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/licenses/${PROJECT_NAME}"
         COMPONENT library
     )
+
+    if(SDL3RTF_INSTALL_MAN)
+        SDL_generate_manpages(
+            SYMBOL "RTF_CreateContext"
+            WIKIHEADERS_PL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build-scripts/wikiheaders.pl"
+        )
+    endif()
 endif()
 
-if(SDL2RTF_SAMPLES)
+if(SDL3RTF_SAMPLES)
     add_executable(showrtf examples/showrtf.c)
 
-    find_package(SDL2main QUIET)
-
     foreach(prog showrtf)
-        if(MINGW)
-            target_link_libraries(${prog} PRIVATE mingw32)
-            target_link_options(${prog} PRIVATE -mwindows)
-        endif()
-        target_link_libraries(${prog} PRIVATE SDL2_rtf::${sdl2_rtf_export_name})
-        if(TARGET SDL2::SDL2main)
-            target_link_libraries(${prog} PRIVATE SDL2::SDL2main)
+        sdl_add_warning_options(${prog} WARNING_AS_ERROR ${SDL3RTF_WERROR})
+        target_link_libraries(${prog} PRIVATE SDL3_rtf::${sdl3_rtf_target_name})
+        target_link_libraries(${prog} PRIVATE ${sdl3ttf_target_name})
+        target_link_libraries(${prog} PRIVATE ${sdl3_target_name})
+
+        if(SDL3RTF_SAMPLES_INSTALL)
+            install(TARGETS ${prog}
+                RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
+            )
         endif()
-        target_link_libraries(${prog} PRIVATE ${sdl2_target_name})
-        target_link_libraries(${prog} PRIVATE ${sdl2ttf_target_name})
     endforeach()
 endif()
diff --git a/Makefile.os2 b/Makefile.os2
deleted file mode 100644
index 4f8e8bf..0000000
--- a/Makefile.os2
+++ /dev/null
@@ -1,86 +0,0 @@
-# Open Watcom makefile to build SDL2rtf.dll for OS/2
-# wmake -f Makefile.os2
-#
-# Remember to edit DEPS_INC and DEPS_LIB below to meet
-# your own environment!.
-
-LIBNAME = SDL2rtf
-MAJOR_VERSION = 2
-MINOR_VERSION = 0
-MICRO_VERSION = 0
-VERSION = $(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION)
-
-TITLENAME = $(LIBNAME) $(VERSION)
-
-LIBFILE = $(LIBNAME).lib
-DLLFILE = $(LIBNAME).dll
-LNKFILE = $(LIBNAME).lnk
-# change DEPS_INC in order to point to the dependency headers.
-DEPS_INC=-IC:\SDL2DEV\h\SDL2 -IC:\SDL2DEV\h
-# change DEPS_LIB in order to point to the dependency libraries.
-DEPS_LIB=C:\SDL2DEV\lib
-
-SRCS = rtfactn.c rtfreadr.c SDL_rtfreadr.c SDL_rtf.c
-
-OBJS = $(SRCS:.c=.obj)
-
-LIBS = SDL2.lib
-
-CFLAGS_BASE = -bt=os2 -d0 -q -bm -5s -fp5 -fpi87 -sg -oeatxh -ei -j
-# warnings:
-CFLAGS_BASE+= -wx
-# newer OpenWatcom versions enable W303 by default
-CFLAGS_BASE+= -wcd=303
-# include paths:
-CFLAGS_BASE+= -I$(%WATCOM)/h/os2 -I$(%WATCOM)/h
-CFLAGS_BASE+= -I. $(DEPS_INC)
-CFLAGS = $(CFLAGS_BASE)
-# to build a dll:
-CFLAGS+= -bd
-# for DECLSPEC:
-CFLAGS+= -DBUILD_SDL
-
-all: $(DLLFILE) showrtf.exe
-
-$(LIBFILE): $(DLLFILE)
-  @echo * Create library: $@...
-  wlib -b -n -q -c -pa -s -t -zld -ii -io $@ $(DLLFILE)
-
-$(DLLFILE): $(OBJS) $(LNKFILE)
-  @echo * Link: $@
-  wlink @$(LNKFILE)
-
-$(LNKFILE):
-  @%create $@
-  @%append $@ SYSTEM os2v2_dll INITINSTANCE TERMINSTANCE
-  @%append $@ NAME $(LIBNAME)
-  @for %i in ($(OBJS)) do @%append $@ FILE %i
-  @%append $@ OPTION QUIET
-  @%append $@ OPTION DESCRIPTION '@$#libsdl org:$(VERSION)$#@Simple DirectMedia Layer RTF decoding add-on'
-  @%append $@ LIBPATH $(DEPS_LIB)
-  @for %i in ($(LIBS)) do @%append $@ LIB %i
-  @%append $@ OPTION MAP=$*
-  @%append $@ OPTION ELIMINATE
-  @%append $@ OPTION MANYAUTODATA
-  @%append $@ OPTION OSNAME='OS/2 and eComStation'
-  @%append $@ OPTION SHOWDEAD
-
-.c.obj:
-  wcc386 $(CFLAGS) -fo=$^@ $<
-
-showrtf.obj: showrtf.c
-  wcc386 $(CFLAGS_BASE) -fo=$^@ $<
-
-showrtf.exe: $(LIBFILE) showrtf.obj
-  wlink SYS os2v2 OP q LIBPATH $(DEPS_LIB) LIBR {$(LIBFILE) SDL2ttf.lib SDL2.lib} F {showrtf.obj} N showrtf.exe
-
-clean: .SYMBOLIC
-  @echo * Clean: $(TITLENAME)
-  @if exist *.obj rm *.obj
-  @if exist *.err rm *.err
-  @if exist $(LNKFILE) rm $(LNKFILE)
-distclean: .SYMBOLIC clean
-  @if exist $(DLLFILE) rm $(DLLFILE)
-  @if exist $(LIBFILE) rm $(LIBFILE)
-  @if exist *.map rm *.map
-  @if exist *.exe rm *.exe
diff --git a/SDL2_rtf.pc.in b/SDL2_rtf.pc.in
deleted file mode 100644
index 7cff4bb..0000000
--- a/SDL2_rtf.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: SDL2_rtf
-Description: Support for Rich Text Format (.rtf) files with Simple Directmedia Layer
-Version: @VERSION@
-Requires: sdl2 >= @SDL_VERSION@
-Libs: -L${libdir} -lSDL2_rtf
-Cflags: -I${includedir}/SDL2
-Requires.private: @PC_REQUIRES@
-Libs.private: @PC_LIBS@
diff --git a/SDL2_rtf.spec.in b/SDL2_rtf.spec.in
deleted file mode 100644
index 81c3ac5..0000000
--- a/SDL2_rtf.spec.in
+++ /dev/null
@@ -1,66 +0,0 @@
-%define name @PACKAGE@
-%define version @VERSION@
-%define release 1
-
-Summary: Simple DirectMedia Layer - Sample RTF Rendering Library
-Name: %{name}
-Version: %{version}
-Release: %{release}
-Source0: %{name}-%{version}.tar.gz
-License: LGPL
-Group: System Environment/Libraries
-BuildRoot: /var/tmp/%{name}-buildroot
-Prefix: %{_prefix}
-Packager: Hakan Tandogan <hakan@iconsult.com>
-#BuildRequires: SDL-devel
-#BuildRequires: SDL_ttf-devel
-
-%description
-This library allows you to display Rich Text Format files in SDL
-applications.
-
-%package devel
-Summary: Libraries, includes and more to develop SDL applications.
-Group: Development/Libraries
-Requires: %{name}
-Requires: SDL-devel
-Requires: SDL_ttf-devel
-
-%description devel
-This library allows you to display Rich Text Format files in SDL
-applications.
-
-%prep
-rm -rf ${RPM_BUILD_ROOT}
-
-%setup
-
-%build
-CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%{prefix}
-make
-
-%install
-rm -rf $RPM_BUILD_ROOT
-make install prefix=$RPM_BUILD_ROOT/%{prefix}
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-%doc README.txt CHANGES.txt LICENSE.txt
-%{prefix}/lib/lib*.so.*
-
-%files devel
-%defattr(-,root,root)
-%{prefix}/lib/lib*.a
-%{prefix}/lib/lib*.la
-%{prefix}/lib/lib*.so
-%{prefix}/include/SDL/
-
-%changelog
-* Wed Jan 19 2000 Sam Lantinga 
-- converted to get package information from configure
-* Sun Jan 16 2000 Hakan Tandogan <hakan@iconsult.com>
-- initial spec file
-
diff --git a/test-versioning.sh b/build-scripts/test-versioning.sh
similarity index 56%
rename from test-versioning.sh
rename to build-scripts/test-versioning.sh
index 738252c..23c125a 100755
--- a/test-versioning.sh
+++ b/build-scripts/test-versioning.sh
@@ -4,12 +4,14 @@
 
 set -eu
 
+cd `dirname $0`/..
+
 # Needed so sed doesn't report illegal byte sequences on macOS
 export LC_CTYPE=C
 
-ref_major=$(sed -ne 's/^#define SDL_RTF_MAJOR_VERSION  *//p' SDL_rtf.h)
-ref_minor=$(sed -ne 's/^#define SDL_RTF_MINOR_VERSION  *//p' SDL_rtf.h)
-ref_micro=$(sed -ne 's/^#define SDL_RTF_PATCHLEVEL  *//p' SDL_rtf.h)
+ref_major=$(sed -ne 's/^#define SDL_RTF_MAJOR_VERSION  *//p' include/SDL3/SDL_rtf.h)
+ref_minor=$(sed -ne 's/^#define SDL_RTF_MINOR_VERSION  *//p' include/SDL3/SDL_rtf.h)
+ref_micro=$(sed -ne 's/^#define SDL_RTF_PATCHLEVEL  *//p' include/SDL3/SDL_rtf.h)
 ref_version="${ref_major}.${ref_minor}.${ref_micro}"
 
 tests=0
@@ -26,33 +28,11 @@ not_ok () {
     failed=1
 }
 
-major=$(sed -Ene 's/^m4_define\(\[MAJOR_VERSION_MACRO\], \[([0-9]*)\]\)$/\1/p' configure.ac)
-minor=$(sed -Ene 's/^m4_define\(\[MINOR_VERSION_MACRO\], \[([0-9]*)\]\)$/\1/p' configure.ac)
-micro=$(sed -Ene 's/^m4_define\(\[MICRO_VERSION_MACRO\], \[([0-9]*)\]\)$/\1/p' configure.ac)
-version="${major}.${minor}.${micro}"
-ref_sdl_req=$(sed -ne 's/^SDL_VERSION=//p' configure.ac)
-
-if [ "$ref_version" = "$version" ]; then
-    ok "configure.ac $version"
-else
-    not_ok "configure.ac $version disagrees with SDL_rtf.h $ref_version"
-fi
-
-major=$(sed -ne 's/^MAJOR_VERSION=//p' configure)
-minor=$(sed -ne 's/^MINOR_VERSION=//p' configure)
-micro=$(sed -ne 's/^MICRO_VERSION=//p' configure)
-version="${major}.${minor}.${micro}"
-
-if [ "$ref_version" = "$version" ]; then
-    ok "configure $version"
-else
-    not_ok "configure $version disagrees with SDL_rtf.h $ref_version"
-fi
-
 major=$(sed -ne 's/^set(MAJOR_VERSION \([0-9]*\))$/\1/p' CMakeLists.txt)
 minor=$(sed -ne 's/^set(MINOR_VERSION \([0-9]*\))$/\1/p' CMakeLists.txt)
 micro=$(sed -ne 's/^set(MICRO_VERSION \([0-9]*\))$/\1/p' CMakeLists.txt)
-sdl_req=$(sed -ne 's/^set(SDL_REQUIRED_VERSION \([0-9.]*\))$/\1/p' CMakeLists.txt)
+ref_sdl_req=$(sed -ne 's/^set(SDL_REQUIRED_VERSION \([0-9.]*\))$/\1/p' CMakeLists.txt)
+ref_sdlttf_req=$(sed -ne 's/^set(SDLTTF_REQUIRED_VERSION \([0-9.]*\))$/\1/p' CMakeLists.txt)
 version="${major}.${minor}.${micro}"
 
 if [ "$ref_version" = "$version" ]; then
@@ -61,24 +41,7 @@ else
     not_ok "CMakeLists.txt $version disagrees with SDL_rtf.h $ref_version"
 fi
 
-if [ "$ref_sdl_req" = "$sdl_req" ]; then
-    ok "CMakeLists.txt $sdl_req"
-else
-    not_ok "CMakeLists.txt SDL_REQUIRED_VERSION=$sdl_req disagrees with configure.ac SDL_VERSION=$ref_sdl_req"
-fi
-
-major=$(sed -ne 's/^MAJOR_VERSION *= *//p' Makefile.os2)
-minor=$(sed -ne 's/^MINOR_VERSION *= *//p' Makefile.os2)
-micro=$(sed -ne 's/^MICRO_VERSION *= *//p' Makefile.os2)
-version="${major}.${minor}.${micro}"
-
-if [ "$ref_version" = "$version" ]; then
-    ok "Makefile.os2 $version"
-else
-    not_ok "Makefile.os2 $version disagrees with SDL_rtf.h $ref_version"
-fi
-
-for rcfile in version.rc; do
+for rcfile in src/version.rc; do
     tuple=$(sed -ne 's/^ *FILEVERSION *//p' "$rcfile" | tr -d '\r')
     ref_tuple="${ref_major},${ref_minor},${ref_micro},0"
 
diff --git a/build-scripts/wikiheaders.pl b/build-scripts/wikiheaders.pl
new file mode 100755
index 0000000..bb09faa
--- /dev/null
+++ b/build-scripts/wikiheaders.pl
@@ -0,0 +1,1663 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+use File::Path;
+use Text::Wrap;
+
+$Text::Wrap::huge = 'overflow';
+
+my $projectfullname = 'Simple Directmedia Layer';
+my $projectshortname = 'SDL';
+my $wikisubdir = '';
+my $incsubdir = 'include';
+my $readmesubdir = undef;
+my $apiprefixregex = undef;
+my $versionfname = 'include/SDL_version.h';
+my $versionmajorregex = '\A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z';
+my $versionminorregex = '\A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z';
+my $versionpatchregex = '\A\#define\s+SDL_PATCHLEVEL\s+(\d+)\Z';
+my $mainincludefname = 'SDL.h';
+my $selectheaderregex = '\ASDL.*?\.h\Z';
+my $projecturl = 'https://libsdl.org/';
+my $wikiurl = 'https://wiki.libsdl.org';
+my $bugreporturl = 'https://github.com/libsdl-org/sdlwiki/issues/new';
+my $srcpath = undef;
+my $wikipath = undef;
+my $wikireadmesubdir = 'README';
+my $warn_about_missing = 0;
+my $copy_direction = 0;
+my $optionsfname = undef;
+my $wikipreamble = undef;
+my $changeformat = undef;
+my $manpath = undef;
+
+foreach (@ARGV) {
+    $warn_about_missing = 1, next if $_ eq '--warn-about-missing';
+    $copy_direction = 1, next if $_ eq '--copy-to-headers';
+    $copy_direction = 1, next if $_ eq '--copy-to-header';
+    $copy_direction = -1, next if $_ eq '--copy-to-wiki';
+    $copy_direction = -2, next if $_ eq '--copy-to-manpages';
+    if (/\A--options=(.*)\Z/) {
+        $optionsfname = $1;
+        next;
+    } elsif (/\A--changeformat=(.*)\Z/) {
+        $changeformat = $1;
+        next;
+    } elsif (/\A--manpath=(.*)\Z/) {
+        $manpath = $1;
+        next;
+    }
+    $srcpath = $_, next if not defined $srcpath;
+    $wikipath = $_, next if not defined $wikipath;
+}
+
+my $default_optionsfname = '.wikiheaders-options';
+$default_optionsfname = "$srcpath/$default_optionsfname" if defined $srcpath;
+
+if ((not defined $optionsfname) && (-f $default_optionsfname)) {
+    $optionsfname = $default_optionsfname;
+}
+
+if (defined $optionsfname) {
+    open OPTIONS, '<', $optionsfname or die("Failed to open options file '$optionsfname': $!\n");
+    while (<OPTIONS>) {
+        chomp;
+        if (/\A(.*?)\=(.*)\Z/) {
+            my $key = $1;
+            my $val = $2;
+            $key =~ s/\A\s+//;
+            $key =~ s/\s+\Z//;
+            $val =~ s/\A\s+//;
+            $val =~ s/\s+\Z//;
+            $warn_about_missing = int($val), next if $key eq 'warn_about_missing';
+            $srcpath = $val, next if $key eq 'srcpath';
+            $wikipath = $val, next if $key eq 'wikipath';
+            $apiprefixregex = $val, next if $key eq 'apiprefixregex';
+            $projectfullname = $val, next if $key eq 'projectfullname';
+            $projectshortname = $val, next if $key eq 'projectshortname';
+            $wikisubdir = $val, next if $key eq 'wikisubdir';
+            $incsubdir = $val, next if $key eq 'incsubdir';
+            $readmesubdir = $val, next if $key eq 'readmesubdir';
+            $versionmajorregex = $val, next if $key eq 'versionmajorregex';
+            $versionminorregex = $val, next if $key eq 'versionminorregex';
+            $versionpatchregex = $val, next if $key eq 'versionpatchregex';
+            $versionfname = $val, next if $key eq 'versionfname';
+            $mainincludefname = $val, next if $key eq 'mainincludefname';
+            $selectheaderregex = $val, next if $key eq 'selectheaderregex';
+            $projecturl = $val, next if $key eq 'projecturl';
+            $wikiurl = $val, next if $key eq 'wikiurl';
+            $bugreporturl = $val, next if $key eq 'bugreporturl';
+            $wikipreamble = $val, next if $key eq 'wikipreamble';
+        }
+    }
+    close(OPTIONS);
+}
+
+my $wordwrap_mode = 'mediawiki';
+sub wordwrap_atom {   # don't call this directly.
+    my $str = shift;
+    my $retval = '';
+
+    # wordwrap but leave links intact, even if they overflow.
+    if ($wordwrap_mode eq 'mediawiki') {
+        while ($str =~ s/(.*?)\s*(\[https?\:\/\/.*?\s+.*?\])\s*//ms) {
+            $retval .= fill('', '', $1); # wrap it.
+            $retval .= "\n$2\n";  # don't wrap it.
+        }
+    } elsif ($wordwrap_mode eq 'md') {
+        while ($str =~ s/(.*?)\s*(\[.*?\]\(https?\:\/\/.*?\))\s*//ms) {
+            $retval .= fill('', '', $1); # wrap it.
+            $retval .= "\n$2\n";  # don't wrap it.
+        }
+    }
+
+    return $retval . fill('', '', $str);
+}
+
+sub wordwrap_with_bullet_indent {  # don't call this directly.
+    my $bullet

(Patch may be truncated, please check the link at the top of this post.)