unicode fix
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good

This commit is contained in:
Nishi 2026-09-13 12:21:05 +09:00
commit 8fc51bd1e4
11 changed files with 218 additions and 65 deletions

View file

@ -16,10 +16,12 @@ void MWAPI ok(MwWidget handle, void* user, void* call) {
#ifdef BUG #ifdef BUG
msgbox_wait = MwFALSE; msgbox_wait = MwFALSE;
#endif #endif
MwDestroyWidget(mb);
} }
void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) { void MWAPI file_callback(MwWidget handle, void* user_data, void* call_data) {
mb = MwMessageBox(handle, call_data, "File chosen", MwMB_ICONERROR | MwMB_BUTTONOK); mb = MwMessageBox(window, call_data, "File chosen", MwMB_ICONERROR | MwMB_BUTTONOK);
(void)user_data; (void)user_data;

View file

@ -11,9 +11,9 @@
extern "C" { extern "C" {
#endif #endif
MWDECL char* MWAPI MwACPToUTF8(const char* input); MWDECL char* MWAPI MwACPTextToUTF8Text(const char* input);
MWDECL char* MWAPI MwUTF8ToACP(const char* input); MWDECL char* MWAPI MwUTF8TextToACPText(const char* input);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -20,6 +20,22 @@ extern "C" {
*/ */
MWDECL int MWAPI MwUTF8ToUTF32(const char* input, int* output); MWDECL int MWAPI MwUTF8ToUTF32(const char* input, int* output);
/*!
* @brief Converts UTF-8 to UTF-16
* @brief input Input
* @brief output Output
* @return Bytes this multibyte takes
* @note Output gets NUL terminated
*/
MWDECL int MWAPI MwUTF8ToUTF16(const char* input, wchar_t* output);
/*!
* @brief Converts UTF-8 text to UTF-16 text
* @brief input Input
* @return Output
*/
MWDECL wchar_t* MWAPI MwUTF8TextToUTF16Text(const char* input);
/*! /*!
* @brief Calculates UTF-8 string length * @brief Calculates UTF-8 string length
* @brief input Input * @brief input Input
@ -38,11 +54,33 @@ MWDECL int MWAPI MwUTF8Length(const char* input);
*/ */
MWDECL int MWAPI MwUTF8Copy(const char* src, int srcskip, char* dst, int dstskip, int len); MWDECL int MWAPI MwUTF8Copy(const char* src, int srcskip, char* dst, int dstskip, int len);
/*!
* @brief Returns the count current word takes
* @brief input Input
* @return Count
*/
MWDECL int MWAPI MwUTF16Count(const wchar_t* input);
/*!
* @brief Converts UTF-16 to UTF-8
* @brief input Input
* @brief output Output
* @return Bytes this multibyte takes
*/
MWDECL int MWAPI MwUTF16ToUTF8(const wchar_t* input, char* output);
/*!
* @brief Converts UTF-16 text to UTF-8 text
* @brief input Input
* @return Output
*/
MWDECL char* MWAPI MwUTF16TextToUTF8Text(const wchar_t* input);
/*! /*!
* @brief Converts UTF-32 to UTF-8 * @brief Converts UTF-32 to UTF-8
* @brief input Input * @brief input Input
* @brief output Output * @brief output Output
* @return Bytes this wide byte takes * @return Bytes this multibyte takes
*/ */
MWDECL int MWAPI MwUTF32ToUTF8(int input, char* output); MWDECL int MWAPI MwUTF32ToUTF8(int input, char* output);

View file

@ -67,7 +67,8 @@ if (grep(/^wayland$/, @backends)) {
scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1");
scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1");
scan_wayland_protocol("staging", "fifo", "-v1"); scan_wayland_protocol("staging", "fifo", "-v1");
scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); scan_wayland_protocol_from_file("wlr-layer-shell",
"wlr-layer-shell-unstable-v1.xml");
$gl_libs = "-lGL -lGLU"; $gl_libs = "-lGL -lGLU";
} }

View file

@ -1,21 +1,16 @@
#include <Mw/Milsko.h> #include <Mw/Milsko.h>
#ifndef CP_UTF8 char* MwACPTextToUTF8Text(const char* input) {
#define CP_UTF8 65001
#endif
char* MwACPToUTF8(const char* input) {
#if defined(_WIN32) && defined(MW_HAS_WCHAR) #if defined(_WIN32) && defined(MW_HAS_WCHAR)
int mbbytes = (strlen(input) + 1) * 4; int mbbytes = (strlen(input) + 1) * 4;
int wbytes = 0; int wbytes = 0;
int len; int len;
wchar_t* wout; wchar_t* wout;
char* mbout = malloc(mbbytes); char* mbout;
wbytes = MultiByteToWideChar(CP_ACP, 0, input, strlen(input), NULL, 0) * sizeof(wchar_t); wbytes = MultiByteToWideChar(CP_ACP, 0, input, strlen(input), NULL, 0) * sizeof(wchar_t);
if(wbytes == 0) { if(wbytes == 0) {
free(mbout);
return MwStringDuplicate(input); return MwStringDuplicate(input);
} }
@ -23,23 +18,15 @@ char* MwACPToUTF8(const char* input) {
len = wbytes / sizeof(wchar_t); len = wbytes / sizeof(wchar_t);
memset(wout, 0, wbytes); memset(wout, 0, wbytes);
memset(mbout, 0, mbbytes);
len = MultiByteToWideChar(CP_ACP, 0, input, strlen(input), wout, len); len = MultiByteToWideChar(CP_ACP, 0, input, strlen(input), wout, len);
if(len == 0) { if(len == 0) {
free(mbout);
free(wout); free(wout);
return MwStringDuplicate(input); return MwStringDuplicate(input);
} }
wout[len] = 0; wout[len] = 0;
len = WideCharToMultiByte(CP_UTF8, 0, wout, len, mbout, mbbytes, 0, 0); mbout = MwUTF16TextToUTF8Text(wout);
if(len == 0) {
free(mbout);
free(wout);
return MwStringDuplicate(input);
}
mbout[len] = 0;
free(wout); free(wout);
@ -49,7 +36,7 @@ char* MwACPToUTF8(const char* input) {
#endif #endif
} }
char* MwUTF8ToACP(const char* input) { char* MwUTF8TextToACPText(const char* input) {
#if defined(_WIN32) && defined(MW_HAS_WCHAR) #if defined(_WIN32) && defined(MW_HAS_WCHAR)
int mbbytes = (strlen(input) + 1) * 4; int mbbytes = (strlen(input) + 1) * 4;
int wbytes = 0; int wbytes = 0;
@ -58,25 +45,8 @@ char* MwUTF8ToACP(const char* input) {
wchar_t* wout; wchar_t* wout;
char* mbout = malloc(mbbytes); char* mbout = malloc(mbbytes);
wbytes = MultiByteToWideChar(CP_UTF8, 0, input, strlen(input), NULL, 0) * sizeof(wchar_t); wout = MwUTF8TextToUTF16Text(input);
if(wbytes == 0) { len = wcslen(wout);
free(mbout);
return MwStringDuplicate(input);
}
wout = malloc(wbytes + sizeof(wchar_t));
len = wbytes / sizeof(wchar_t);
memset(wout, 0, wbytes);
memset(mbout, 0, mbbytes);
len = MultiByteToWideChar(CP_UTF8, 0, input, strlen(input), wout, len);
if(len == 0) {
free(mbout);
free(wout);
return MwStringDuplicate(input);
}
wout[len] = 0;
len = WideCharToMultiByte(CP_ACP, 0, wout, len, mbout, mbbytes, 0, 0); len = WideCharToMultiByte(CP_ACP, 0, wout, len, mbout, mbbytes, 0, 0);
if(len == 0) { if(len == 0) {

View file

@ -184,8 +184,8 @@ static void MwDirectoryJoinSingle(char* target, char* p) {
b[0] = DIRSEP; b[0] = DIRSEP;
b[1] = 0; b[1] = 0;
MwStringConcat(target, b); strcat(target, b);
MwStringConcat(target, p); strcat(target, p);
} }
for(i = strlen(target) - 1; i >= 0; i--) { for(i = strlen(target) - 1; i >= 0; i--) {
@ -201,7 +201,7 @@ static void MwDirectoryJoinSingle(char* target, char* p) {
b[0] = DIRSEP; b[0] = DIRSEP;
b[1] = 0; b[1] = 0;
MwStringConcat(target, b); strcat(target, b);
} }
} }

View file

@ -469,7 +469,7 @@ static void scan(MwWidget handle, const char* path, int record) {
if(strcmp(fc->entries[i]->name, ".") == 0 || strcmp(fc->entries[i]->name, "..") == 0) continue; if(strcmp(fc->entries[i]->name, ".") == 0 || strcmp(fc->entries[i]->name, "..") == 0) continue;
if(fc->entries[i]->type == MwDIRECTORY_DIRECTORY) { if(fc->entries[i]->type == MwDIRECTORY_DIRECTORY) {
char date[128]; char date[128];
char* n = MwACPToUTF8(fc->entries[i]->name); char* n = MwACPTextToUTF8Text(fc->entries[i]->name);
MwStringTime(date, fc->entries[i]->mtime); MwStringTime(date, fc->entries[i]->mtime);
@ -487,7 +487,7 @@ static void scan(MwWidget handle, const char* path, int record) {
if(fc->entries[i]->type == MwDIRECTORY_FILE && !fc->dir_only) { if(fc->entries[i]->type == MwDIRECTORY_FILE && !fc->dir_only) {
char date[128]; char date[128];
char size[128]; char size[128];
char* n = MwACPToUTF8(fc->entries[i]->name); char* n = MwACPTextToUTF8Text(fc->entries[i]->name);
MwStringTime(date, fc->entries[i]->mtime); MwStringTime(date, fc->entries[i]->mtime);
MwStringSize(size, fc->entries[i]->size); MwStringSize(size, fc->entries[i]->size);

View file

@ -5,6 +5,8 @@ static HANDLE(WINAPI* _AddFontMemResourceEx)(PVOID pFileView, DWORD cjSize, PVOI
static BOOL(WINAPI* _RemoveFontMemResourceEx)(HANDLE h) = NULL; static BOOL(WINAPI* _RemoveFontMemResourceEx)(HANDLE h) = NULL;
static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize, PVOID pvResrved, DWORD* pNumFonts); static HANDLE WINAPI _AddFontMemResourceExPolyFill(PVOID pFileView, DWORD cjSize, PVOID pvResrved, DWORD* pNumFonts);
static BOOL WINAPI _RemoveFontMemResourceExPolyFill(HANDLE h); static BOOL WINAPI _RemoveFontMemResourceExPolyFill(HANDLE h);
static BOOL(WINAPI* _TextOutW)(HDC hdc, int x, int y, LPCWSTR lpString, int c);
static BOOL(WINAPI* _GetTextExtentPoint32W)(HDC hdc, LPCWSTR lpString, int c, LPSIZE psizl);
struct _MwFLFont { struct _MwFLFont {
HANDLE handle; HANDLE handle;
@ -19,8 +21,9 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c
HBITMAP hbm; HBITMAP hbm;
RGBQUAD* bits = NULL; RGBQUAD* bits = NULL;
HDC hmdc; HDC hmdc;
char* t = MwUTF8ToACP(text);
unsigned char* px; unsigned char* px;
char* t;
wchar_t* t16;
int y, x; int y, x;
MwRect r; MwRect r;
MwLLPixmap p; MwLLPixmap p;
@ -33,14 +36,20 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c
int old_bkmode = SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT); int old_bkmode = SetBkMode(handle->lowlevel->gdi.hDC, TRANSPARENT);
COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, RGB(color->common.red, color->common.green, color->common.blue)); COLORREF old_color = SetTextColor(handle->lowlevel->gdi.hDC, RGB(color->common.red, color->common.green, color->common.blue));
TextOut(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t)); if(_TextOutW == NULL) {
t = MwUTF8TextToACPText(text);
TextOutA(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t));
free(t);
} else {
t16 = MwUTF8TextToUTF16Text(text);
TextOutW(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t16, wcslen(t16));
free(t16);
}
SetTextColor(handle->lowlevel->gdi.hDC, old_color); SetTextColor(handle->lowlevel->gdi.hDC, old_color);
SetBkMode(handle->lowlevel->gdi.hDC, old_bkmode); SetBkMode(handle->lowlevel->gdi.hDC, old_bkmode);
SelectObject(handle->lowlevel->gdi.hDC, old_font); SelectObject(handle->lowlevel->gdi.hDC, old_font);
free(t);
return 0; return 0;
} }
@ -64,7 +73,15 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c
SelectObject(hmdc, hbm); SelectObject(hmdc, hbm);
SelectObject(hmdc, ttf->font); SelectObject(hmdc, ttf->font);
TextOut(hmdc, 0, 0, t, strlen(t)); if(_TextOutW == NULL) {
t = MwUTF8TextToACPText(text);
TextOutA(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t, strlen(t));
free(t);
} else {
t16 = MwUTF8TextToUTF16Text(text);
TextOutW(handle->lowlevel->gdi.hDC, point->x, point->y - th / 2, t16, wcslen(t16));
free(t16);
}
DeleteDC(hmdc); DeleteDC(hmdc);
@ -90,18 +107,22 @@ static int GDI_MwDrawText(MwWidget handle, MwFLFont ttf, MwPoint* point, const c
free(px); free(px);
DeleteObject(hbm); DeleteObject(hbm);
free(t);
return 0; return 0;
} }
static int GDI_MwTextWidth(MwFLFont ttf, const char* text) { static int GDI_MwTextWidth(MwFLFont ttf, const char* text) {
char* t = MwUTF8ToACP(text);
SIZE sz; SIZE sz;
GetTextExtentPoint32(ttf->dc, t, strlen(t), &sz); if(_GetTextExtentPoint32W == NULL) {
char* t = MwUTF8TextToACPText(text);
GetTextExtentPoint32A(ttf->dc, t, strlen(t), &sz);
free(t); free(t);
} else {
wchar_t* t16 = MwUTF8TextToUTF16Text(text);
_GetTextExtentPoint32W(ttf->dc, t16, wcslen(t16), &sz);
free(t16);
}
return sz.cx; return sz.cx;
} }
@ -255,6 +276,9 @@ int MwFL_GDISetup(void) {
if(!_RemoveFontMemResourceEx) { if(!_RemoveFontMemResourceEx) {
_RemoveFontMemResourceEx = _RemoveFontMemResourceExPolyFill; _RemoveFontMemResourceEx = _RemoveFontMemResourceExPolyFill;
} }
_TextOutW = (void*)GetProcAddress(gdilib, "TextOutW");
_GetTextExtentPoint32W = (void*)GetProcAddress(gdilib, "GetTextExtentPoint32W");
} }
MwFLDrawText = GDI_MwDrawText; MwFLDrawText = GDI_MwDrawText;

View file

@ -58,6 +58,50 @@ int MwUTF8ToUTF32(const char* input, int* output) {
return b; return b;
} }
int MwUTF8ToUTF16(const char* input, wchar_t* output) {
int o;
int n = MwUTF8ToUTF32(input, &o);
if(n == 0 || n >= 0x10ffff) return 0;
if(o < 0x10000) {
output[0] = o;
output[1] = 0;
} else {
output[0] = (o - 0x10000) / 0x400 + 0xd800;
output[1] = (o - 0x10000) % 0x400 + 0xdc00;
output[2] = 0;
}
return n;
}
wchar_t* MwUTF8TextToUTF16Text(const char* input) {
wchar_t* o = malloc((MwUTF8Length(input) * 2 + 1) * sizeof(*o));
int n = 0;
wchar_t buffer[3];
o[0] = 0;
while(input[0] != 0) {
int new = MwUTF8ToUTF16(input, buffer);
if(new == 0) {
free(o);
return NULL;
}
memcpy(o + n, buffer, wcslen(buffer) * sizeof(*o));
input += new;
n += wcslen(buffer);
}
o[n] = 0;
return o;
}
int MwUTF8Length(const char* input) { int MwUTF8Length(const char* input) {
int out; int out;
int len = 0; int len = 0;
@ -97,6 +141,80 @@ int MwUTF8Copy(const char* src, int srcskip, char* dst, int dstskip, int len) {
return total; return total;
} }
static int is_u16_high(wchar_t ch) {
return 0xd800 <= ch && ch < 0xdc00;
}
static int is_u16_low(wchar_t ch) {
return 0xdc00 <= ch && ch < 0xe000;
}
int MwUTF16Count(const wchar_t* input) {
if(is_u16_high(input[0])) {
if(is_u16_low(input[1])) {
return 2;
} else if(input[1] == 0) {
return 2;
} else {
return 0;
}
} else if(is_u16_low(input[0])) {
if(input[1] == 0) {
return 2;
} else {
return 0;
}
} else {
return 1;
}
}
int MwUTF16ToUTF8(const wchar_t* input, char* output) {
if(is_u16_high(input[0])) {
if(is_u16_low(input[1])) {
return MwUTF32ToUTF8(0x10000 + (CAST_I32(input[0]) - 0xd800) * 0x400 + (CAST_I32(input[1]) - 0xdc00), output);
} else if(input[1] == 0) {
return MwUTF32ToUTF8(input[0], output);
} else {
return 0;
}
} else if(is_u16_low(input[0])) {
if(input[1] == 0) {
return MwUTF32ToUTF8(input[0], output);
} else {
return 0;
}
} else {
return MwUTF32ToUTF8(input[0], output);
}
}
char* MwUTF16TextToUTF8Text(const wchar_t* input) {
char* o = malloc(4 * wcslen(input) + 1);
int n = 0;
char buffer[4];
o[0] = 0;
while(input[0]) {
int new = MwUTF16ToUTF8(input, buffer);
if(new == 0) {
free(o);
return NULL;
}
memcpy(o + n, buffer, new);
input += MwUTF16Count(input);
n += new;
}
o[n] = 0;
return o;
}
int MwUTF32ToUTF8(int input, char* output) { int MwUTF32ToUTF8(int input, char* output) {
if(input < 128) { if(input < 128) {
output[0] = input; output[0] = input;