patch 9.1.1347: small problems with gui_w32.c

Problem:  small problems with gui_w32.c
Solution: fix compile warnings and refactor code (John Marriott)

Compiler (clang v20.1.3) warnings on `_OnMenuSelect()` and
`_OnGetDpiScaledSize()`:
```
clang -c -I. -Iproto -DWIN32 -DWINVER=0x0601 -D_WIN32_WINNT=0x0601
-DHAVE_PATHDEF -DFEAT_HUGE -DHAVE_STDINT_H -D__USE_MINGW_ANSI_STDIO
-pipe -Wall -Wno-deprecated-declarations -D_REENTRANT -U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=1 -Wall -Wextra -Wshadow -Wstrict-prototypes
-Wmissing-prototypes -Wno-deprecated-declarations
-Wno-error=missing-field-initializers -Werror=uninitialized
-Wunused-but-set-variable -DEXITFREE -DFEAT_GUI_MSWIN -DFEAT_CLIPBOARD
gui_w32.c -o gobjx86-64/gui_w32.o
gui_w32.c:5038:55: warning: comparison of integers of different signs:
'UINT' (aka 'unsigned int') and 'int' [-Wsign-compare]
 5038 |                 && GetMenuState(s_menuBar, pMenu->id, MF_BYCOMMAND) != -1)
      | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~
gui_w32.c:5054:26: warning: unused parameter 'hwnd' [-Wunused-parameter]
 5054 | _OnGetDpiScaledSize(HWND hwnd, UINT dpi, SIZE *size)
      |                          ^
2 warnings generated.
```

This commit contains the following changes:
- Fixes Warning 1:
  The prototype of `GetMenuState()` says that it returns a UINT, but
  returns -1 on failure. Huh?!?

  Also, Microsoft says that this function has been superseded (see
  https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmenustate)
  and replaced by `GetMenuItemInfo()`. Both of these functions have a
  minimum support of Windows 2000.
  Therefore in `_OnMenuSelect()`, replace the call to `GetMenuState()`
  with `GetMenuItemInfo()`.

- Fixes Warning 2:
  Add `UNUSED` to the definition of `_OnGetDpiScaledSize()`.

- Simplify `logfont2name()`.
- Add small optimisations in `_OnNotify()` and `gui_mch_do_spawn()`.
- Add out-of-memory check in `gui_mch_do_spawn()`.
- Code cosmetics (see definitions of `process_message_usual_key_classic()`
  and `process_message()`).

closes: #17208

Signed-off-by: John Marriott <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/gui_w32.c b/src/gui_w32.c
index 0debae9..4e6eca8 100644
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -2157,7 +2157,8 @@
  * Experimental implementation, introduced in v8.2.4807
  * "processing key event in Win32 GUI is not ideal"
  */
-static void process_message_usual_key_experimental(UINT vk, const MSG *pmsg)
+    static void
+process_message_usual_key_experimental(UINT vk, const MSG *pmsg)
 {
     WCHAR	ch[8];
     int		len;
@@ -2237,7 +2238,8 @@
 /*
  * "Classic" implementation, existing prior to v8.2.4807
  */
-static void process_message_usual_key_classic(UINT vk, const MSG *pmsg)
+    static void
+process_message_usual_key_classic(UINT vk, const MSG *pmsg)
 {
     char_u	string[40];
 
@@ -3673,12 +3675,11 @@
     static char_u *
 logfont2name(LOGFONTW lf)
 {
-    char	*p;
-    char	*res;
     char	*charset_name;
     char	*quality_name;
     char	*font_name;
-    int		points;
+    size_t	res_size;
+    char	*res;
 
     font_name = (char *)utf16_to_enc(lf.lfFaceName, NULL);
     if (font_name == NULL)
@@ -3686,43 +3687,48 @@
     charset_name = charset_id2name((int)lf.lfCharSet);
     quality_name = quality_id2name((int)lf.lfQuality);
 
-    res = alloc(strlen(font_name) + 30
-		    + (charset_name == NULL ? 0 : strlen(charset_name) + 2)
-		    + (quality_name == NULL ? 0 : strlen(quality_name) + 2));
+    res_size = STRLEN(font_name) + 30
+		    + (charset_name == NULL ? 0 : STRLEN(charset_name) + 2)
+		    + (quality_name == NULL ? 0 : STRLEN(quality_name) + 2);
+    res = alloc(res_size);
     if (res != NULL)
     {
-	p = res;
+	char	*p;
+	int	points;
+	size_t	res_len;
+
+	// replace spaces in font_name with underscores.
+	for (p = font_name; *p != NUL; ++p)
+	{
+	    if (isspace(*p))
+		*p = '_';
+	}
+
 	// make a normal font string out of the lf thing:
 	points = pixels_to_points(
 			 lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE);
 	if (lf.lfWeight == FW_NORMAL || lf.lfWeight == FW_BOLD)
-	    sprintf((char *)p, "%s:h%d", font_name, points);
+	    res_len = vim_snprintf_safelen(
+		(char *)res, res_size, "%s:h%d", font_name, points);
 	else
-	    sprintf((char *)p, "%s:h%d:W%ld", font_name, points, lf.lfWeight);
-	while (*p)
-	{
-	    if (*p == ' ')
-		*p = '_';
-	    ++p;
-	}
-	if (lf.lfItalic)
-	    STRCAT(p, ":i");
-	if (lf.lfWeight == FW_BOLD)
-	    STRCAT(p, ":b");
-	if (lf.lfUnderline)
-	    STRCAT(p, ":u");
-	if (lf.lfStrikeOut)
-	    STRCAT(p, ":s");
+	    res_len = vim_snprintf_safelen(
+		(char *)res, res_size, "%s:h%d:W%ld", font_name, points, lf.lfWeight);
+
+	res_len += vim_snprintf_safelen(
+	    (char *)res + res_len,
+	    res_size - res_len,
+	    "%s%s%s%s",
+	    lf.lfItalic ? ":i" : "",
+	    lf.lfWeight ? ":b" : "",
+	    lf.lfUnderline ? ":u" : "",
+	    lf.lfStrikeOut ? ":s" : "");
+
 	if (charset_name != NULL)
-	{
-	    STRCAT(p, ":c");
-	    STRCAT(p, charset_name);
-	}
+	    res_len += vim_snprintf_safelen((char *)res + res_len,
+		res_size - res_len, ":c%s", charset_name);
 	if (quality_name != NULL)
-	{
-	    STRCAT(p, ":q");
-	    STRCAT(p, quality_name);
-	}
+	    vim_snprintf((char *)res + res_len,
+		res_size - res_len, ":q%s", quality_name);
     }
 
     vim_free(font_name);
@@ -4975,9 +4981,10 @@
 		else
 		{
 		    LPNMTTDISPINFO	lpdi = (LPNMTTDISPINFO)hdr;
+		    size_t		len = STRLEN(str);
 
-		    if (STRLEN(str) < sizeof(lpdi->szText)
-			    || ((tt_text = vim_strsave(str)) == NULL))
+		    if (len < sizeof(lpdi->szText)
+			    || ((tt_text = vim_strnsave(str, len)) == NULL))
 			vim_strncpy((char_u *)lpdi->szText, str,
 				sizeof(lpdi->szText) - 1);
 		    else
@@ -5020,7 +5027,6 @@
 	    == MF_HILITE
 	    && (State & MODE_CMDLINE) == 0)
     {
-	UINT	    idButton;
 	vimmenu_T   *pMenu;
 	static int  did_menu_tip = FALSE;
 
@@ -5032,17 +5038,23 @@
 	    did_menu_tip = FALSE;
 	}
 
-	idButton = (UINT)LOWORD(wParam);
-	pMenu = gui_mswin_find_menu(root_menu, idButton);
-	if (pMenu != NULL && pMenu->strings[MENU_INDEX_TIP] != 0
-		&& GetMenuState(s_menuBar, pMenu->id, MF_BYCOMMAND) != -1)
+	pMenu = gui_mswin_find_menu(root_menu, (UINT)LOWORD(wParam));
+	if (pMenu != NULL && pMenu->strings[MENU_INDEX_TIP] != NULL)
 	{
-	    ++msg_hist_off;
-	    msg((char *)pMenu->strings[MENU_INDEX_TIP]);
-	    --msg_hist_off;
-	    setcursor();
-	    out_flush();
-	    did_menu_tip = TRUE;
+	    MENUITEMINFO menuinfo;
+
+	    menuinfo.cbSize = sizeof(MENUITEMINFO);
+	    menuinfo.fMask = MIIM_ID;		    // We only want to check if the menu item exists,
+						    // so retrieve something simple.
+	    if (GetMenuItemInfo(s_menuBar, pMenu->id, FALSE, &menuinfo))
+	    {
+		++msg_hist_off;
+		msg((char *)pMenu->strings[MENU_INDEX_TIP]);
+		--msg_hist_off;
+		setcursor();
+		out_flush();
+		did_menu_tip = TRUE;
+	    }
 	}
 	return 0L;
     }
@@ -5051,7 +5063,7 @@
 #endif
 
     static BOOL
-_OnGetDpiScaledSize(HWND hwnd, UINT dpi, SIZE *size)
+_OnGetDpiScaledSize(HWND hwnd UNUSED, UINT dpi, SIZE *size)
 {
     int		old_width, old_height;
     int		new_width, new_height;
@@ -5394,7 +5406,12 @@
 	if (session == NULL)
 	    goto error;
 	savebg = p_bg;
-	p_bg = vim_strsave((char_u *)"light");	// Set 'bg' to "light".
+	p_bg = vim_strnsave((char_u *)"light", 5);	// Set 'bg' to "light".
+	if (p_bg == NULL)
+	{
+	    p_bg = savebg;
+	    goto error;
+	}
 	ret = write_session_file(session);
 	vim_free(p_bg);
 	p_bg = savebg;