Skip to content

Commit d43f4c2

Browse files
authored
fix(windows): incorrect UTF8/GBK string encoding handling (#74)
1 parent 4d1dafc commit d43f4c2

1 file changed

Lines changed: 28 additions & 16 deletions

File tree

src/tray_windows.c

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ enum IconType {
3636
};
3737

3838
static WNDCLASSEX wc;
39-
static NOTIFYICONDATA nid;
39+
static NOTIFYICONDATAW nid;
4040
static HWND hwnd;
4141
static HMENU hmenu = NULL;
4242
static void (*notification_cb)() = 0;
@@ -83,7 +83,7 @@ static LRESULT CALLBACK _tray_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARA
8383
}
8484

8585
if (msg == wm_taskbarcreated) {
86-
Shell_NotifyIcon(NIM_ADD, &nid);
86+
Shell_NotifyIconW(NIM_ADD, &nid);
8787
return 0;
8888
}
8989

@@ -94,11 +94,11 @@ static HMENU _tray_menu(struct tray_menu *m, UINT *id) {
9494
HMENU hmenu = CreatePopupMenu();
9595
for (; m != NULL && m->text != NULL; m++, (*id)++) {
9696
if (strcmp(m->text, "-") == 0) {
97-
InsertMenu(hmenu, *id, MF_SEPARATOR, TRUE, "");
97+
InsertMenuW(hmenu, *id, MF_SEPARATOR, TRUE, L"");
9898
} else {
99-
MENUITEMINFO item;
99+
MENUITEMINFOW item;
100100
memset(&item, 0, sizeof(item));
101-
item.cbSize = sizeof(MENUITEMINFO);
101+
item.cbSize = sizeof(MENUITEMINFOW);
102102
item.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
103103
item.fType = 0;
104104
item.fState = 0;
@@ -113,10 +113,22 @@ static HMENU _tray_menu(struct tray_menu *m, UINT *id) {
113113
item.fState |= MFS_CHECKED;
114114
}
115115
item.wID = *id;
116-
item.dwTypeData = (LPSTR) m->text;
116+
117+
// Convert UTF-8 text to UTF-16 (wide string)
118+
int wide_size = MultiByteToWideChar(CP_UTF8, 0, m->text, -1, NULL, 0);
119+
wchar_t *wide_text = (wchar_t *) malloc(wide_size * sizeof(wchar_t));
120+
if (wide_text == NULL) {
121+
DestroyMenu(hmenu);
122+
return NULL;
123+
}
124+
MultiByteToWideChar(CP_UTF8, 0, m->text, -1, wide_text, wide_size);
125+
126+
item.dwTypeData = wide_text;
117127
item.dwItemData = (ULONG_PTR) m;
118128

119-
InsertMenuItem(hmenu, *id, TRUE, &item);
129+
InsertMenuItemW(hmenu, *id, TRUE, &item);
130+
// Free the allocated wide string
131+
free(wide_text);
120132
}
121133
}
122134
return hmenu;
@@ -231,12 +243,12 @@ int tray_init(struct tray *tray) {
231243
UpdateWindow(hwnd);
232244

233245
memset(&nid, 0, sizeof(nid));
234-
nid.cbSize = sizeof(NOTIFYICONDATA);
246+
nid.cbSize = sizeof(NOTIFYICONDATAW);
235247
nid.hWnd = hwnd;
236248
nid.uID = 0;
237249
nid.uFlags = NIF_ICON | NIF_MESSAGE;
238250
nid.uCallbackMessage = WM_TRAY_CALLBACK_MESSAGE;
239-
Shell_NotifyIcon(NIM_ADD, &nid);
251+
Shell_NotifyIconW(NIM_ADD, &nid);
240252

241253
tray_update(tray);
242254
return 0;
@@ -275,36 +287,36 @@ void tray_update(struct tray *tray) {
275287
nid.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
276288
}
277289
if (tray->tooltip != 0 && strlen(tray->tooltip) > 0) {
278-
strncpy(nid.szTip, tray->tooltip, sizeof(nid.szTip));
290+
MultiByteToWideChar(CP_UTF8, 0, tray->tooltip, -1, nid.szTip, sizeof(nid.szTip) / sizeof(wchar_t));
279291
nid.uFlags |= NIF_TIP;
280292
}
281293
QUERY_USER_NOTIFICATION_STATE notification_state;
282294
HRESULT ns = SHQueryUserNotificationState(&notification_state);
283295
int can_show_notifications = ns == S_OK && notification_state == QUNS_ACCEPTS_NOTIFICATIONS;
284296
if (can_show_notifications == 1 && tray->notification_title != 0 && strlen(tray->notification_title) > 0) {
285-
strncpy(nid.szInfoTitle, tray->notification_title, sizeof(nid.szInfoTitle));
297+
MultiByteToWideChar(CP_UTF8, 0, tray->notification_title, -1, nid.szInfoTitle, sizeof(nid.szInfoTitle) / sizeof(wchar_t));
286298
nid.uFlags |= NIF_INFO;
287299
} else if ((nid.uFlags & NIF_INFO) == NIF_INFO) {
288-
strncpy(nid.szInfoTitle, "", sizeof(nid.szInfoTitle));
300+
nid.szInfoTitle[0] = L'\0';
289301
}
290302
if (can_show_notifications == 1 && tray->notification_text != 0 && strlen(tray->notification_text) > 0) {
291-
strncpy(nid.szInfo, tray->notification_text, sizeof(nid.szInfo));
303+
MultiByteToWideChar(CP_UTF8, 0, tray->notification_text, -1, nid.szInfo, sizeof(nid.szInfo) / sizeof(wchar_t));
292304
} else if ((nid.uFlags & NIF_INFO) == NIF_INFO) {
293-
strncpy(nid.szInfo, "", sizeof(nid.szInfo));
305+
nid.szInfo[0] = L'\0';
294306
}
295307
if (can_show_notifications == 1 && tray->notification_cb != NULL) {
296308
notification_cb = tray->notification_cb;
297309
}
298310

299-
Shell_NotifyIcon(NIM_MODIFY, &nid);
311+
Shell_NotifyIconW(NIM_MODIFY, &nid);
300312

301313
if (prevmenu != NULL) {
302314
DestroyMenu(prevmenu);
303315
}
304316
}
305317

306318
void tray_exit(void) {
307-
Shell_NotifyIcon(NIM_DELETE, &nid);
319+
Shell_NotifyIconW(NIM_DELETE, &nid);
308320
_destroy_icon_cache();
309321
if (hmenu != 0) {
310322
DestroyMenu(hmenu);

0 commit comments

Comments
 (0)