runtime(filetype): improve *.h filetype detection

This commit changes *.h files to default to C (instead of C++), and
deprecates the existing `g:c_syntax_for_h` and `g:ch_syntax_for_h`
variables in favor of a unified `g:filetype_h`, like is used for other
ambiguous file extensions.

closes: #17135

Signed-off-by: Amelia Clarke <selene@perilune.dev>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index a0be930..0c0b872 100644
--- a/runtime/autoload/dist/ft.vim
+++ b/runtime/autoload/dist/ft.vim
@@ -3,7 +3,7 @@
 # Vim functions for file type detection
 #
 # Maintainer:		The Vim Project <https://github.com/vim/vim>
-# Last Change:		2025 Apr 15
+# Last Change:		2025 Apr 19
 # Former Maintainer:	Bram Moolenaar <Bram@vim.org>
 
 # These functions are moved here from runtime/filetype.vim to make startup
@@ -203,19 +203,36 @@
   setf c
 enddef
 
-export def FTheader()
-  if match(getline(1, min([line("$"), 200])), '^@\(interface\|end\|class\)') > -1
-    if exists("g:c_syntax_for_h")
-      setf objc
-    else
-      setf objcpp
+# Searches within the first `maxlines` lines of the file for distinctive
+# Objective-C or C++ syntax and returns the appropriate filetype. Returns a
+# null_string if the search was inconclusive.
+def CheckObjCOrCpp(maxlines = 100): string
+  var n = 1
+  while n < maxlines && n <= line('$')
+    const line = getline(n)
+    if line =~ '\v^\s*\@%(class|interface|end)>'
+      return 'objcpp'
+    elseif line =~ '\v^\s*%(class|namespace|template|using)>'
+      return 'cpp'
     endif
-  elseif exists("g:c_syntax_for_h")
+    ++n
+  endwhile
+  return null_string
+enddef
+
+# Determines whether a *.h file is C, C++, Ch, or Objective-C/Objective-C++.
+export def FTheader()
+  if exists('g:filetype_h')
+    execute $'setf {g:filetype_h}'
+  elseif exists('g:c_syntax_for_h')
     setf c
-  elseif exists("g:ch_syntax_for_h")
+  elseif exists('g:ch_syntax_for_h')
     setf ch
   else
-    setf cpp
+    # Search the first 100 lines of the file for distinctive Objective-C or C++
+    # syntax and set the filetype accordingly. Otherwise, use C as the default
+    # filetype.
+    execute $'setf {CheckObjCOrCpp() ?? 'c'}'
   endif
 enddef
 
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index c0bf1e6..77bf5f3 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -1,4 +1,4 @@
-*filetype.txt*	For Vim version 9.1.  Last change: 2025 Apr 16
+*filetype.txt*	For Vim version 9.1.  Last change: 2025 Apr 19
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -153,7 +153,11 @@
 	*.f		g:filetype_f		|ft-forth-syntax|
 	*.frm		g:filetype_frm		|ft-form-syntax|
 	*.fs		g:filetype_fs		|ft-forth-syntax|
-	*.h		g:c_syntax_for_h	|ft-c-syntax|
+	*.h		g:c_syntax_for_h	|ft-c-syntax|	(deprecated)
+	*.h		g:ch_syntax_for_h	|ft-ch-syntax|	(deprecated)
+	*.h		g:filetype_h		|ft-c-syntax|
+						|ft-ch-syntax|
+						|ft-cpp-syntax|
 	*.i		g:filetype_i		|ft-progress-syntax|
 	*.inc		g:filetype_inc
 	*.lsl		g:filetype_lsl
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index ae89bd9..a8fbe1a 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -1,4 +1,4 @@
-*syntax.txt*	For Vim version 9.1.  Last change: 2025 Apr 15
+*syntax.txt*	For Vim version 9.1.  Last change: 2025 Apr 19
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -1056,8 +1056,12 @@
 *c_ansi_typedefs*	 ... but do standard ANSI types
 *c_ansi_constants*	 ... but do standard ANSI constants
 *c_no_utf*		don't highlight \u and \U in strings
-*c_syntax_for_h*	for *.h files use C syntax instead of C++ and use objc
-			syntax instead of objcpp
+*c_syntax_for_h*	use C syntax for *.h files instead of C++/ObjC/ObjC++
+			(NOTE: This variable is deprecated and no longer
+			 necessary, as *.h files now default to C, unless the
+			 file contains C++ or Objective-C syntax. If the
+			 automated detection fails, the default filetype can
+			 be adjusted using `g:filetype_h`.)
 *c_no_if0*		don't highlight "#if 0" blocks as comments
 *c_no_cformat*		don't highlight %-formats in strings
 *c_no_c99*		don't highlight C99 standard items
@@ -1116,8 +1120,11 @@
 
 By setting a variable you can tell Vim to use Ch syntax for *.h files, instead
 of C or C++: >
-	:let ch_syntax_for_h = 1
+	:let g:filetype_h = 'ch'
 
+NOTE: In previous versions of Vim, the following (now-deprecated) variable was
+used, but is no longer the preferred approach: >
+	:let ch_syntax_for_h = 1
 
 CHILL						*chill.vim* *ft-chill-syntax*
 
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index e850074..da74e25 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -1,7 +1,7 @@
 " Vim support file to detect file types
 "
 " Maintainer:	The Vim Project <https://github.com/vim/vim>
-" Last Change:	2025 Apr 18
+" Last Change:	2025 Apr 19
 " Former Maintainer:	Bram Moolenaar <Bram@vim.org>
 
 " Listen very carefully, I will say this only once
@@ -436,9 +436,8 @@
 " https://clang.llvm.org/docs/StandardCPlusPlusModules.html#file-name-requirement
 au BufNewFile,BufRead *.cppm,*.ccm,*.cxxm,*.c++m setf cpp
 
-" .h files can be C, Ch C++, ObjC or ObjC++.
-" Set c_syntax_for_h if you want C, ch_syntax_for_h if you want Ch. ObjC is
-" detected automatically.
+" .h files can be C, C++, Ch, Objective-C, or Objective-C++.
+" Set g_filetype_h to set a different filetype
 au BufNewFile,BufRead *.h			call dist#ft#FTheader()
 
 " Ch (CHscript)