1
0
forked from aniani/vim

patch 9.0.1991: no cmdline completion for setting the font

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>
This commit is contained in:
Yee Cheng Chin
2023-10-05 20:54:21 +02:00
committed by Christian Brabandt
parent ea746f9e86
commit 290b887e8c
9 changed files with 362 additions and 9 deletions

View File

@@ -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,
@@ -2889,6 +2915,100 @@ init_logfont(LOGFONTW *lf)
return OK;
}
/*
* 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;