Skip to content

Commit 06ebeb4

Browse files
Hybrid Machineclaude
andcommitted
feat: build ComparePlus as macOS dylib
Add CMake target for ComparePlus plugin, following the HelloMacNote plugin SDK pattern. The plugin builds as a .dylib MODULE library with -undefined dynamic_lookup for host symbol resolution. Shim additions to support compilation: - versionhelpers.h: stub Windows version checks (always true) - winbase.h: DLL_PROCESS_ATTACH constants, INI profile function declarations, _wfopen_s/_itow_s/_snwprintf_s safe CRT functions - winuser.h: SendInput/INPUT structs (stub), SM_CXMENUCHECK - win32_profile.mm: GetPrivateProfileIntW/StringW and WritePrivateProfileStringW backed by real INI file parsing All 6 core source files compile: Compare.cpp, NppHelpers.cpp, Tools.cpp, Strings.cpp, UserSettings.cpp, Engine/Engine.cpp. Phase 2 of issue #100 — ComparePlus macOS port. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7c668aa commit 06ebeb4

7 files changed

Lines changed: 386 additions & 0 deletions

File tree

macos/CMakeLists.txt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,59 @@ add_custom_target(install_sample_plugin
456456
COMMENT "Installing HelloMacNote plugin to ~/Library/Application Support/MacNote++/plugins/"
457457
)
458458

459+
# ============================================================
460+
# Plugin: ComparePlus (macOS port)
461+
# ============================================================
462+
set(COMPARE_PLUS_DIR "${NPP_ROOT}/plugins/comparePlus")
463+
464+
add_library(ComparePlus MODULE
465+
"${COMPARE_PLUS_DIR}/src/Compare.cpp"
466+
"${COMPARE_PLUS_DIR}/src/NppHelpers.cpp"
467+
"${COMPARE_PLUS_DIR}/src/Tools.cpp"
468+
"${COMPARE_PLUS_DIR}/src/Strings.cpp"
469+
"${COMPARE_PLUS_DIR}/src/UserSettings.cpp"
470+
"${COMPARE_PLUS_DIR}/src/Engine/Engine.cpp"
471+
)
472+
target_include_directories(ComparePlus PRIVATE
473+
"${SHIM_INCLUDE_DIR}"
474+
"${COMPARE_PLUS_DIR}/src/NppAPI"
475+
"${COMPARE_PLUS_DIR}/src"
476+
"${COMPARE_PLUS_DIR}/src/Engine"
477+
"${COMPARE_PLUS_DIR}/src/Icons"
478+
"${COMPARE_PLUS_DIR}/src/nlohmann"
479+
"${COMPARE_PLUS_DIR}/src/AboutDlg"
480+
"${COMPARE_PLUS_DIR}/src/SettingsDlg"
481+
"${COMPARE_PLUS_DIR}/src/CompareOptionsDlg"
482+
"${COMPARE_PLUS_DIR}/src/VisualFiltersDlg"
483+
"${COMPARE_PLUS_DIR}/src/NavDlg"
484+
"${COMPARE_PLUS_DIR}/src/ProgressDlg"
485+
"${COMPARE_PLUS_DIR}/src/NppAPI/DockingFeature"
486+
"${COMPARE_PLUS_DIR}/src/boost_regex/include"
487+
"${SCINTILLA_INCLUDE_DIR}"
488+
)
489+
target_compile_definitions(ComparePlus PRIVATE
490+
UNICODE
491+
_UNICODE
492+
BOOST_REGEX_STANDALONE
493+
)
494+
set_target_properties(ComparePlus PROPERTIES
495+
PREFIX ""
496+
SUFFIX ".dylib"
497+
OUTPUT_NAME "ComparePlus"
498+
)
499+
target_compile_options(ComparePlus PRIVATE -Wno-deprecated-declarations)
500+
target_link_options(ComparePlus PRIVATE -undefined dynamic_lookup)
501+
502+
add_custom_target(install_compare_plus
503+
DEPENDS ComparePlus
504+
COMMAND ${CMAKE_COMMAND} -E make_directory
505+
"$ENV{HOME}/Library/Application Support/MacNote++/plugins/ComparePlus"
506+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
507+
"$<TARGET_FILE:ComparePlus>"
508+
"$ENV{HOME}/Library/Application Support/MacNote++/plugins/ComparePlus/ComparePlus.dylib"
509+
COMMENT "Installing ComparePlus plugin to ~/Library/Application Support/MacNote++/plugins/"
510+
)
511+
459512
# ============================================================
460513
# Packaging: App bundle, code signing, and DMG
461514
# ============================================================

macos/shim/include/tchar.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,37 @@ inline int swprintf_s(wchar_t* buf, size_t count, const wchar_t* fmt, ...) {
167167
#define _vsnwprintf vswprintf
168168
#define sscanf_s sscanf
169169

170+
// _snwprintf_s: safe variant of _snwprintf
171+
inline int _snwprintf_s(wchar_t* buf, size_t sizeOfBuffer, size_t count, const wchar_t* fmt, ...) {
172+
(void)count;
173+
va_list args;
174+
va_start(args, fmt);
175+
int r = vswprintf(buf, sizeOfBuffer, fmt, args);
176+
va_end(args);
177+
return r;
178+
}
179+
180+
// _itow_s: safe variant of _itow
181+
inline errno_t _itow_s(int value, wchar_t* buf, size_t sizeInWords, int radix) {
182+
if (!buf || sizeInWords == 0) return EINVAL;
183+
if (radix == 10)
184+
swprintf(buf, sizeInWords, L"%d", value);
185+
else if (radix == 16)
186+
swprintf(buf, sizeInWords, L"%x", value);
187+
else if (radix == 8)
188+
swprintf(buf, sizeInWords, L"%o", value);
189+
else
190+
buf[0] = L'\0';
191+
return 0;
192+
}
193+
194+
// _wfopen_s: safe variant of _wfopen
195+
inline errno_t _wfopen_s(FILE** pFile, const wchar_t* filename, const wchar_t* mode) {
196+
if (!pFile) return EINVAL;
197+
*pFile = _wfopen(filename, mode);
198+
return (*pFile) ? 0 : errno;
199+
}
200+
170201
// memcpy_s / memmove_s
171202
#include <cstring>
172203
#include <cerrno>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// versionhelpers.h — macOS shim for Windows version helper macros
2+
// On macOS, all version checks return true (we're "at least Windows 10").
3+
4+
#pragma once
5+
6+
inline bool IsWindows7OrGreater() { return true; }
7+
inline bool IsWindows8OrGreater() { return true; }
8+
inline bool IsWindows10OrGreater() { return true; }

macos/shim/include/winbase.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@
99
#include <cstring>
1010
#include <unistd.h>
1111

12+
// ============================================================
13+
// DLL entry point constants
14+
// ============================================================
15+
#ifndef DLL_PROCESS_ATTACH
16+
#define DLL_PROCESS_ATTACH 1
17+
#define DLL_THREAD_ATTACH 2
18+
#define DLL_THREAD_DETACH 3
19+
#define DLL_PROCESS_DETACH 0
20+
#endif
21+
1222
// ============================================================
1323
// Error codes
1424
// ============================================================
@@ -1148,3 +1158,56 @@ inline HRESULT GetApplicationRestartSettings(HANDLE hProcess, LPWSTR pwzCommandl
11481158
if (pdwFlags) *pdwFlags = 0;
11491159
return E_NOTIMPL;
11501160
}
1161+
1162+
// ============================================================
1163+
// INI file (Private Profile) functions — declarations only.
1164+
// Implemented in win32_profile.mm (ObjC++ for Foundation access).
1165+
// ============================================================
1166+
UINT GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName);
1167+
DWORD GetPrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault,
1168+
LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName);
1169+
BOOL WritePrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpString, LPCWSTR lpFileName);
1170+
1171+
// ============================================================
1172+
// MSVC CRT safe string functions (not in tchar.h for non-tchar code)
1173+
// ============================================================
1174+
1175+
#include <cerrno>
1176+
#include <cstdarg>
1177+
1178+
// Forward-declare _wfopen from winbase.h (defined above)
1179+
#ifndef _WFOPEN_DEFINED
1180+
FILE* _wfopen(const wchar_t* filename, const wchar_t* mode);
1181+
#define _WFOPEN_DEFINED
1182+
#endif
1183+
1184+
inline errno_t _wfopen_s(FILE** pFile, const wchar_t* filename, const wchar_t* mode)
1185+
{
1186+
if (!pFile) return EINVAL;
1187+
*pFile = _wfopen(filename, mode);
1188+
return (*pFile) ? 0 : errno;
1189+
}
1190+
1191+
inline errno_t _itow_s(int value, wchar_t* buf, size_t sizeInWords, int radix)
1192+
{
1193+
if (!buf || sizeInWords == 0) return EINVAL;
1194+
if (radix == 10)
1195+
swprintf(buf, sizeInWords, L"%d", value);
1196+
else if (radix == 16)
1197+
swprintf(buf, sizeInWords, L"%x", value);
1198+
else if (radix == 8)
1199+
swprintf(buf, sizeInWords, L"%o", value);
1200+
else
1201+
buf[0] = L'\0';
1202+
return 0;
1203+
}
1204+
1205+
inline int _snwprintf_s(wchar_t* buf, size_t sizeOfBuffer, size_t count, const wchar_t* fmt, ...)
1206+
{
1207+
(void)count;
1208+
va_list args;
1209+
va_start(args, fmt);
1210+
int r = vswprintf(buf, sizeOfBuffer, fmt, args);
1211+
va_end(args);
1212+
return r;
1213+
}

macos/shim/include/windows.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,12 @@ int GetDeviceCaps(HDC hdc, int index);
457457
COLORREF GetSysColor(int nIndex);
458458
HBRUSH GetSysColorBrush(int nIndex);
459459
int GetSystemMetrics(int nIndex);
460+
461+
#ifndef SM_CXMENUCHECK
462+
#define SM_CXMENUCHECK 71
463+
#define SM_CYMENUCHECK 72
464+
#endif
465+
460466
BOOL SystemParametersInfoW(UINT uiAction, UINT uiParam, LPVOID pvParam, UINT fWinIni);
461467
#define SystemParametersInfo SystemParametersInfoW
462468

macos/shim/include/winuser.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,3 +1929,56 @@ inline BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
19291929
return TRUE;
19301930
}
19311931
BOOL EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc, LPARAM lParam);
1932+
1933+
// ============================================================
1934+
// SendInput (stub for macOS — used by ComparePlus for click simulation)
1935+
// ============================================================
1936+
#define INPUT_MOUSE 0
1937+
#define INPUT_KEYBOARD 1
1938+
#define INPUT_HARDWARE 2
1939+
1940+
#define MOUSEEVENTF_LEFTDOWN 0x0002
1941+
#define MOUSEEVENTF_LEFTUP 0x0004
1942+
1943+
struct MOUSEINPUT
1944+
{
1945+
LONG dx;
1946+
LONG dy;
1947+
DWORD mouseData;
1948+
DWORD dwFlags;
1949+
DWORD time;
1950+
ULONG_PTR dwExtraInfo;
1951+
};
1952+
1953+
struct KEYBDINPUT
1954+
{
1955+
WORD wVk;
1956+
WORD wScan;
1957+
DWORD dwFlags;
1958+
DWORD time;
1959+
ULONG_PTR dwExtraInfo;
1960+
};
1961+
1962+
struct HARDWAREINPUT
1963+
{
1964+
DWORD uMsg;
1965+
WORD wParamL;
1966+
WORD wParamH;
1967+
};
1968+
1969+
struct INPUT
1970+
{
1971+
DWORD type;
1972+
union
1973+
{
1974+
MOUSEINPUT mi;
1975+
KEYBDINPUT ki;
1976+
HARDWAREINPUT hi;
1977+
};
1978+
};
1979+
1980+
inline UINT SendInput(UINT nInputs, INPUT* pInputs, int cbSize)
1981+
{
1982+
(void)nInputs; (void)pInputs; (void)cbSize;
1983+
return 0; // Stub — no input simulation on macOS
1984+
}

0 commit comments

Comments
 (0)