summaryrefslogtreecommitdiffstats
path: root/src/os_mswin.c
diff options
context:
space:
mode:
authorYee Cheng Chin <ychin.git@gmail.com>2023-10-05 20:54:21 +0200
committerChristian Brabandt <cb@256bit.org>2023-10-05 20:54:21 +0200
commit290b887e8cc2c0d3dfc7f315b2052472c7c589cc (patch)
tree1b5285384cc6ed9e3a0bce9051d1e4b201196161 /src/os_mswin.c
parentea746f9e862092aef3d4e95c64d116759b9fabe0 (diff)
patch 9.0.1991: no cmdline completion for setting the fontv9.0.1991
Problem: no cmdline completion for setting the font Solution: enable it on Win32 and GTK builds Add guifont cmdline completion (for Windows and GTK) For Windows, auto-complete will only suggest monospace fonts as that's the only types allowed. Will also suggest font options after the colon, including suggesting the current font size for convenience, and misc charset and quality options like `cANSI` and `qCLEARTYPE`. For GTK, auto-complete will suggest only monospace fonts for `guifont` but will include all fonts for `guifontwide`. The completion code doesn't currently suggest the current font size, as the GTK guifont format does not have a clear delimiter (':' for other platforms). closes: #13264 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
Diffstat (limited to 'src/os_mswin.c')
-rw-r--r--src/os_mswin.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/os_mswin.c b/src/os_mswin.c
index aa5fe5243e..46f73752f9 100644
--- a/src/os_mswin.c
+++ b/src/os_mswin.c
@@ -2819,6 +2819,32 @@ points_to_pixels(WCHAR *str, WCHAR **end, int vertical, long_i pprinter_dc)
return pixels;
}
+/*
+ * Convert pixel into point size. This is a reverse of points_to_pixels.
+ */
+ static double
+pixels_to_points(int pixels, int vertical, long_i pprinter_dc)
+{
+ double points = 0;
+ HWND hwnd = (HWND)0;
+ HDC hdc;
+ HDC printer_dc = (HDC)pprinter_dc;
+
+ if (printer_dc == NULL)
+ {
+ hwnd = GetDesktopWindow();
+ hdc = GetWindowDC(hwnd);
+ }
+ else
+ hdc = printer_dc;
+
+ points = pixels * 72.0 / GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX);
+ if (printer_dc == NULL)
+ ReleaseDC(hwnd, hdc);
+
+ return points;
+}
+
static int CALLBACK
font_enumproc(
ENUMLOGFONTW *elf,
@@ -2890,6 +2916,100 @@ init_logfont(LOGFONTW *lf)
}
/*
+ * Call back for EnumFontFamiliesW in expand_font_enumproc.
+ *
+ */
+ static int CALLBACK
+expand_font_enumproc(
+ ENUMLOGFONTW *elf,
+ NEWTEXTMETRICW *ntm UNUSED,
+ DWORD type UNUSED,
+ LPARAM lparam)
+{
+ LOGFONTW *lf = (LOGFONTW*)elf;
+
+# ifndef FEAT_PROPORTIONAL_FONTS
+ // Ignore non-monospace fonts without further ado
+ if ((ntm->tmPitchAndFamily & 1) != 0)
+ return 1;
+# endif
+
+ // Filter only on ANSI. Otherwise will see a lot of random fonts that we
+ // usually don't want.
+ if (lf->lfCharSet != ANSI_CHARSET)
+ return 1;
+
+ int (*add_match)(char_u *) = (int (*)(char_u *))lparam;
+
+ WCHAR *faceNameW = lf->lfFaceName;
+ char_u *faceName = utf16_to_enc(faceNameW, NULL);
+ if (!faceName)
+ return 0;
+
+ add_match(faceName);
+ vim_free(faceName);
+
+ return 1;
+}
+
+/*
+ * Cmdline expansion for setting 'guifont'. Will enumerate through all
+ * monospace fonts for completion. If used after ':', will expand to possible
+ * font configuration options like font sizes.
+ *
+ * This function has "gui" in its name because in some platforms (GTK) font
+ * handling is done by the GUI code, whereas in Windows it's part of the
+ * platform code.
+ */
+ void
+gui_mch_expand_font(optexpand_T *args, void *param UNUSED, int (*add_match)(char_u *val))
+{
+ expand_T *xp = args->oe_xp;
+ if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
+ {
+ char buf[30];
+
+ // Always fill in with the current font size as first option for
+ // convenience. We simply round to the closest integer for simplicity.
+ int font_height = (int)round(
+ pixels_to_points(-current_font_height, TRUE, (long_i)NULL));
+ vim_snprintf(buf, ARRAY_LENGTH(buf), "h%d", font_height);
+ add_match((char_u *)buf);
+
+ // Note: Keep this in sync with get_logfont(). Don't include 'c' and
+ // 'q' as we fill in all the values below.
+ static char *(p_gfn_win_opt_values[]) = {
+ "h" , "w" , "W" , "b" , "i" , "u" , "s"};
+ for (size_t i = 0; i < ARRAY_LENGTH(p_gfn_win_opt_values); i++)
+ add_match((char_u *)p_gfn_win_opt_values[i]);
+
+ struct charset_pair *cp;
+ for (cp = charset_pairs; cp->name != NULL; ++cp)
+ {
+ vim_snprintf(buf, ARRAY_LENGTH(buf), "c%s", cp->name);
+ add_match((char_u *)buf);
+ }
+ struct quality_pair *qp;
+ for (qp = quality_pairs; qp->name != NULL; ++qp)
+ {
+ vim_snprintf(buf, ARRAY_LENGTH(buf), "q%s", qp->name);
+ add_match((char_u *)buf);
+ }
+ return;
+ }
+
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+
+ EnumFontFamiliesW(hdc,
+ NULL,
+ (FONTENUMPROCW)expand_font_enumproc,
+ (LPARAM)add_match);
+
+ ReleaseDC(hwnd, hdc);
+}
+
+/*
* Compare a UTF-16 string and an ASCII string literally.
* Only works all the code points are inside ASCII range.
*/
@@ -2995,6 +3115,7 @@ get_logfont(
{
switch (*p++)
{
+ // Note: Keep this in sync with gui_mch_expand_font().
case L'h':
lf->lfHeight = - points_to_pixels(p, &p, TRUE, (long_i)printer_dc);
break;