Skip to content

Commit 325137c

Browse files
authored
Merge pull request #330 from AlchemyViewer/feature/native-spellcheck-backends
Add native NSSpellCheck and WinSpellCheck spellchecking support
2 parents 7963260 + c27faac commit 325137c

13 files changed

Lines changed: 959 additions & 169 deletions

indra/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ else ()
7676
option(USE_SDL_WINDOW "Build with SDL based window management and input (experimental on Windows)" OFF)
7777
endif ()
7878

79+
# Spell checking backend
80+
cmake_dependent_option(USE_NSSPELLCHECKER "Use the native macOS NSSpellChecker instead of Hunspell" ON "APPLE" OFF)
81+
cmake_dependent_option(USE_WINSPELLCHECK "Use the native Windows Spell Checking API instead of Hunspell" ON "WIN32" OFF)
82+
7983
# Configure crash reporting
8084
option(RELEASE_CRASH_REPORTING "Enable use of crash reporting in release builds" OFF)
8185
option(NON_RELEASE_CRASH_REPORTING "Enable use of crash reporting in developer builds" OFF)
@@ -181,6 +185,10 @@ if(BUILD_DULLAHAN_EXAMPLE)
181185
list(APPEND VCPKG_MANIFEST_FEATURES "dullahan-example")
182186
endif()
183187

188+
if (NOT USE_NSSPELLCHECKER AND NOT USE_WINSPELLCHECK)
189+
list(APPEND VCPKG_MANIFEST_FEATURES "hunspell")
190+
endif()
191+
184192
# Export compile_commands.json for ninja and makefile generators
185193
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
186194

@@ -275,6 +283,7 @@ include(Mesa)
275283
include(Meshoptimizer)
276284
include(Mikktspace)
277285
include(NDOF)
286+
include(NSSpellChecker)
278287
include(NVAPI)
279288
include(OpenAL)
280289
include(OpenGL)
@@ -297,6 +306,7 @@ include(Vorbis)
297306
include(WebP)
298307
include(WebRTC)
299308
include(websocketpp)
309+
include(WinSpellCheck)
300310
include(xxHash)
301311
include(ZLIBNG)
302312

indra/cmake/Copy3rdPartyLibs.cmake

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,13 @@ if(WINDOWS)
8888
endif()
8989
elseif(DARWIN)
9090
set(vcpkg_lib_dir "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib")
91-
set(release_libs
92-
"libhunspell-1.7.0.dylib"
93-
)
91+
if (USE_NSSPELLCHECKER)
92+
set(release_libs "")
93+
else()
94+
set(release_libs
95+
"libhunspell-1.7.0.dylib"
96+
)
97+
endif()
9498
elseif(LINUX)
9599
set(vcpkg_lib_dir "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib")
96100
set(release_libs "")

indra/cmake/Hunspell.cmake

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ include_guard()
33

44
add_library(ll::hunspell INTERFACE IMPORTED)
55

6-
find_package(PkgConfig REQUIRED)
6+
if (NOT USE_NSSPELLCHECKER AND NOT USE_WINSPELLCHECK)
7+
find_package(PkgConfig REQUIRED)
78

8-
pkg_check_modules(hunspell REQUIRED IMPORTED_TARGET GLOBAL hunspell)
9-
target_link_libraries(ll::hunspell INTERFACE PkgConfig::hunspell)
9+
pkg_check_modules(hunspell REQUIRED IMPORTED_TARGET GLOBAL hunspell)
10+
target_link_libraries(ll::hunspell INTERFACE PkgConfig::hunspell)
11+
endif()

indra/cmake/NSSpellChecker.cmake

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# -*- cmake -*-
2+
3+
include_guard()
4+
5+
if (USE_NSSPELLCHECKER)
6+
# Link target for the macOS NSSpellChecker engine (llspellcheckengine_mac.mm). No compile
7+
# definitions are needed: the engine is selected by which source CMake compiles, and the shared
8+
# llspellcheck.h is platform-clean (it only forward-declares the abstract LLSpellCheckEngine).
9+
add_library(ll::nsspellchecker INTERFACE IMPORTED)
10+
target_link_libraries(ll::nsspellchecker INTERFACE "-framework AppKit" "-framework Foundation")
11+
endif ()

indra/cmake/WinSpellCheck.cmake

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- cmake -*-
2+
3+
include_guard()
4+
5+
if (USE_WINSPELLCHECK)
6+
# Link target for the Windows Spell Checking engine (llspellcheckengine_win32.cpp). ole32 provides
7+
# CoInitializeEx/CoCreateInstance/CoTaskMemFree/CoUninitialize; <spellcheck.h> ships with the
8+
# Windows SDK and the API uses LPCWSTR (not BSTR), so no oleaut32/uuid.lib is required. No compile
9+
# definitions are needed: the engine is selected by which source CMake compiles, and the shared
10+
# llspellcheck.h is platform-clean (it only forward-declares the abstract LLSpellCheckEngine).
11+
add_library(ll::winspellcheck INTERFACE IMPORTED)
12+
target_link_libraries(ll::winspellcheck INTERFACE ole32)
13+
endif ()

indra/llui/CMakeLists.txt

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ target_sources(llui
7070
llsearcheditor.cpp
7171
llslider.cpp
7272
llsliderctrl.cpp
73-
llspellcheck.cpp
7473
llspinctrl.cpp
7574
llstatbar.cpp
7675
llstatgraph.cpp
@@ -190,6 +189,7 @@ target_sources(llui
190189
llsliderctrl.h
191190
llslider.h
192191
llspellcheck.h
192+
llspellcheckengine.h
193193
llspellcheckmenuhandler.h
194194
llspinctrl.h
195195
llstatbar.h
@@ -234,6 +234,20 @@ target_sources(llui
234234
llxyvector.h
235235
)
236236

237+
# Spell checking: the backend-agnostic LLSpellChecker core (llspellcheck.cpp) is always compiled;
238+
# exactly one platform engine is selected by build option — native macOS NSSpellChecker
239+
# (Objective-C++), native Windows Spell Checking API, or Hunspell (default).
240+
target_sources(llui PRIVATE llspellcheck.cpp)
241+
if (USE_NSSPELLCHECKER)
242+
target_sources(llui PRIVATE llspellcheckengine_mac.mm)
243+
set_source_files_properties(llspellcheckengine_mac.mm PROPERTIES SKIP_PRECOMPILE_HEADERS TRUE)
244+
elseif (USE_WINSPELLCHECK)
245+
target_sources(llui PRIVATE llspellcheckengine_win32.cpp)
246+
set_source_files_properties(llspellcheckengine_win32.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS TRUE)
247+
else ()
248+
target_sources(llui PRIVATE llspellcheckengine_hunspell.cpp)
249+
endif ()
250+
237251
SET(llurlentry_TEST_DEPENDENCIES
238252
llurlmatch.cpp
239253
llurlregistry.cpp
@@ -259,14 +273,28 @@ target_link_libraries(llui
259273
llxml
260274
llmath
261275
llcommon
262-
ll::hunspell
263276
)
264277

278+
if (USE_NSSPELLCHECKER)
279+
target_link_libraries(llui PUBLIC ll::nsspellchecker)
280+
elseif (USE_WINSPELLCHECK)
281+
target_link_libraries(llui PUBLIC ll::winspellcheck)
282+
else ()
283+
target_link_libraries(llui PUBLIC ll::hunspell)
284+
endif ()
285+
265286
target_precompile_headers(llui REUSE_FROM llprecompiled)
266287

267288
# Add tests
268289
if(BUILD_TESTING)
269-
set(test_libs llmessage llcorehttp llxml llrender llcommon ll::hunspell)
290+
if (USE_NSSPELLCHECKER)
291+
set(spellcheck_lib ll::nsspellchecker)
292+
elseif (USE_WINSPELLCHECK)
293+
set(spellcheck_lib ll::winspellcheck)
294+
else ()
295+
set(spellcheck_lib ll::hunspell)
296+
endif ()
297+
set(test_libs llmessage llcorehttp llxml llrender llcommon ${spellcheck_lib})
270298

271299
SET(llui_TEST_SOURCE_FILES
272300
llurlmatch.cpp
@@ -275,7 +303,7 @@ if(BUILD_TESTING)
275303
LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
276304

277305
# INTEGRATION TESTS
278-
set(test_libs llui llmessage llcorehttp llxml llrender llcommon ll::hunspell)
306+
set(test_libs llui llmessage llcorehttp llxml llrender llcommon ${spellcheck_lib})
279307
set(test_project llui)
280308
LL_ADD_INTEGRATION_TEST(llurlentry llurlentry.cpp "${test_libs}" "${test_project}")
281309
LL_ADD_INTEGRATION_TEST(llemojidictionary llemojidictionary.cpp "${test_libs}" "${test_project}")

0 commit comments

Comments
 (0)