flatlaf-natives-windows: fixed link error on GitHub Actions
Some checks failed
CI / build (push) Has been cancelled
CI / release (push) Has been cancelled
Error Prone / error-prone (push) Has been cancelled
Native Libraries / Natives (macos-latest) (push) Has been cancelled
Native Libraries / Natives (ubuntu-24.04-arm) (push) Has been cancelled
Native Libraries / Natives (ubuntu-latest) (push) Has been cancelled
Native Libraries / Natives (windows-latest) (push) Has been cancelled

for some unknown reason (maybe newer Visual C++ version),
MSVC on GitHub Actions no longer inlines methods `wcscpy` and `wcslen`,
which results in linker error:
`error LNK2019: unresolved external symbol wcscpy/wcslen`
This commit is contained in:
Karl Tauber
2025-10-31 12:01:20 +01:00
parent df8212b49e
commit 10677d469f
3 changed files with 35 additions and 17 deletions

View File

@@ -83,3 +83,16 @@ int __cdecl printf( const char* format, ... ) {
return retValue; return retValue;
} }
*/ */
size_t rt_wcslen( const wchar_t* str ) {
const wchar_t* s = str;
while( *s != '\0' )
s++;
return (size_t) (s - str);
}
void rt_wcscpy( wchar_t* dest, const wchar_t* src ) {
while( *src != '\0' )
*dest++ = *src++;
*dest = '\0';
}

View File

@@ -29,6 +29,7 @@
// declare external methods // declare external methods
extern HWND getWindowHandle( JNIEnv* env, jobject window ); extern HWND getWindowHandle( JNIEnv* env, jobject window );
extern size_t rt_wcslen( const wchar_t* str );
// declare internal methods // declare internal methods
static jobjectArray getFiles( JNIEnv* env, jboolean open, IFileDialog* dialog ); static jobjectArray getFiles( JNIEnv* env, jboolean open, IFileDialog* dialog );
@@ -202,7 +203,7 @@ static jobjectArray newJavaStringArray( JNIEnv* env, jsize count ) {
} }
static jstring newJavaString( JNIEnv* env, LPWSTR str ) { static jstring newJavaString( JNIEnv* env, LPWSTR str ) {
return env->NewString( reinterpret_cast<jchar*>( str ), static_cast<jsize>( wcslen( str ) ) ); return env->NewString( reinterpret_cast<jchar*>( str ), static_cast<jsize>( rt_wcslen( str ) ) );
} }
//---- JNI methods ------------------------------------------------------------ //---- JNI methods ------------------------------------------------------------

View File

@@ -32,6 +32,10 @@
// declare external fields // declare external fields
extern HINSTANCE _instance; extern HINSTANCE _instance;
// declare external methods
extern size_t rt_wcslen( const wchar_t* str );
extern void rt_wcscpy( wchar_t* dest, const wchar_t* src );
// declare internal methods // declare internal methods
static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title, LPCWSTR text, static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title, LPCWSTR text,
int defaultButton, int buttonCount, LPCWSTR* buttons ); int defaultButton, int buttonCount, LPCWSTR* buttons );
@@ -154,8 +158,8 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
int th = 0; int th = 0;
if( text == NULL ) if( text == NULL )
text = L""; text = L"";
LPWSTR wrappedText = new WCHAR[wcslen( text ) + 1]; LPWSTR wrappedText = new WCHAR[rt_wcslen( text ) + 1];
wcscpy( wrappedText, text ); rt_wcscpy( wrappedText, text );
LPWSTR lineStart = wrappedText; LPWSTR lineStart = wrappedText;
for( LPWSTR t = wrappedText; ; t++ ) { for( LPWSTR t = wrappedText; ; t++ ) {
if( *t != '\n' && *t != 0 ) if( *t != '\n' && *t != 0 )
@@ -193,11 +197,11 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
th += LABEL_HEIGHT; th += LABEL_HEIGHT;
// duplicate string // duplicate string
LPWSTR wrappedText2 = new WCHAR[wcslen( wrappedText ) + 1 + 1]; LPWSTR wrappedText2 = new WCHAR[rt_wcslen( wrappedText ) + 1 + 1];
// use wcscpy(), instead of wcsncpy(), because this method is inlined and does not require linking to runtime lib // use wcscpy(), instead of wcsncpy(), because this method is inlined and does not require linking to runtime lib
wcscpy( wrappedText2, wrappedText ); rt_wcscpy( wrappedText2, wrappedText );
wrappedText2[breakIndex] = '\n'; wrappedText2[breakIndex] = '\n';
wcscpy( wrappedText2 + breakIndex + 1, wrappedText + breakIndex ); rt_wcscpy( wrappedText2 + breakIndex + 1, wrappedText + breakIndex );
// delete old text // delete old text
delete[] wrappedText; delete[] wrappedText;
@@ -262,11 +266,11 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
// (approximately) calculate memory size needed for in-memory template // (approximately) calculate memory size needed for in-memory template
int templSize = (sizeof(DLGTEMPLATE) + /*menu*/ 2 + /*class*/ 2 + /*title*/ 2) int templSize = (sizeof(DLGTEMPLATE) + /*menu*/ 2 + /*class*/ 2 + /*title*/ 2)
+ ((sizeof(DLGITEMTEMPLATE) + /*class*/ 4 + /*title/icon*/ 4 + /*creation data*/ 2) * (/*icon+text*/2 + buttonCount)) + ((sizeof(DLGITEMTEMPLATE) + /*class*/ 4 + /*title/icon*/ 4 + /*creation data*/ 2) * (/*icon+text*/2 + buttonCount))
+ (title != NULL ? (wcslen( title ) + 1) * sizeof(wchar_t) : 0) + (title != NULL ? (rt_wcslen( title ) + 1) * sizeof(wchar_t) : 0)
+ /*fontPointSize*/ 2 + ((wcslen( fontFaceName ) + 1) * sizeof(wchar_t)) + /*fontPointSize*/ 2 + ((rt_wcslen( fontFaceName ) + 1) * sizeof(wchar_t))
+ ((wcslen( wrappedText ) + 1) * sizeof(wchar_t)); + ((rt_wcslen( wrappedText ) + 1) * sizeof(wchar_t));
for( int i = 0; i < buttonCount; i++ ) for( int i = 0; i < buttonCount; i++ )
templSize += ((wcslen( buttons[i] ) + 1) * sizeof(wchar_t)); templSize += ((rt_wcslen( buttons[i] ) + 1) * sizeof(wchar_t));
templSize += (2 * (1 + 1 + buttonCount)); // necessary for DWORD alignment templSize += (2 * (1 + 1 + buttonCount)); // necessary for DWORD alignment
templSize += 100; // some reserve templSize += 100; // some reserve
@@ -291,15 +295,15 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
*lpw++ = 0; // no menu *lpw++ = 0; // no menu
*lpw++ = 0; // predefined dialog box class (by default) *lpw++ = 0; // predefined dialog box class (by default)
if( title != NULL ) { if( title != NULL ) {
wcscpy( (LPWSTR) lpw, title ); rt_wcscpy( (LPWSTR) lpw, title );
lpw += wcslen( title ) + 1; lpw += rt_wcslen( title ) + 1;
} else } else
*lpw++ = 0; // no title *lpw++ = 0; // no title
// for DS_SETFONT // for DS_SETFONT
*lpw++ = fontPointSize; *lpw++ = fontPointSize;
wcscpy( (LPWSTR) lpw, fontFaceName ); rt_wcscpy( (LPWSTR) lpw, fontFaceName );
lpw += wcslen( fontFaceName ) + 1; lpw += rt_wcslen( fontFaceName ) + 1;
//---- define icon ---- //---- define icon ----
@@ -335,7 +339,7 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
lpw = (LPWORD) (lpdit + 1); lpw = (LPWORD) (lpdit + 1);
*lpw++ = 0xffff; *lpw++ = 0x0082; // Static class *lpw++ = 0xffff; *lpw++ = 0x0082; // Static class
wcscpy( (LPWSTR) lpw, wrappedText ); lpw += wcslen( wrappedText ) + 1; // text rt_wcscpy( (LPWSTR) lpw, wrappedText ); lpw += rt_wcslen( wrappedText ) + 1; // text
*lpw++ = 0; // creation data *lpw++ = 0; // creation data
@@ -356,7 +360,7 @@ static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title,
lpw = (LPWORD) (lpdit + 1); lpw = (LPWORD) (lpdit + 1);
*lpw++ = 0xffff; *lpw++ = 0x0080; // Button class *lpw++ = 0xffff; *lpw++ = 0x0080; // Button class
wcscpy( (LPWSTR) lpw, buttons[i] ); lpw += wcslen( buttons[i] ) + 1; // text rt_wcscpy( (LPWSTR) lpw, buttons[i] ); lpw += rt_wcslen( buttons[i] ) + 1; // text
*lpw++ = 0; // creation data *lpw++ = 0; // creation data
bx += bw[i] + BUTTON_GAP; bx += bw[i] + BUTTON_GAP;
@@ -394,7 +398,7 @@ static INT_PTR CALLBACK messageDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam,
static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen ) { static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen ) {
SIZE size{ 0 }; SIZE size{ 0 };
::GetTextExtentPoint32( hdc, str, (strLen >= 0) ? strLen : wcslen( str ), &size ); ::GetTextExtentPoint32( hdc, str, (strLen >= 0) ? strLen : rt_wcslen( str ), &size );
return pixel2dluX( size.cx ); return pixel2dluX( size.cx );
} }