comparison src/os_mswin.c @ 33480:f8dd278ab05f v9.0.1991

patch 9.0.1991: no cmdline completion for setting the font Commit: https://github.com/vim/vim/commit/290b887e8cc2c0d3dfc7f315b2052472c7c589cc Author: Yee Cheng Chin <ychin.git@gmail.com> Date: Thu Oct 5 20:54:21 2023 +0200 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>
author Christian Brabandt <cb@256bit.org>
date Thu, 05 Oct 2023 21:00:07 +0200
parents 397ff3169248
children 1629cc65d78d
comparison
equal deleted inserted replaced
33479:e88e84676ad5 33480:f8dd278ab05f
2817 2817
2818 *end = str; 2818 *end = str;
2819 return pixels; 2819 return pixels;
2820 } 2820 }
2821 2821
2822 /*
2823 * Convert pixel into point size. This is a reverse of points_to_pixels.
2824 */
2825 static double
2826 pixels_to_points(int pixels, int vertical, long_i pprinter_dc)
2827 {
2828 double points = 0;
2829 HWND hwnd = (HWND)0;
2830 HDC hdc;
2831 HDC printer_dc = (HDC)pprinter_dc;
2832
2833 if (printer_dc == NULL)
2834 {
2835 hwnd = GetDesktopWindow();
2836 hdc = GetWindowDC(hwnd);
2837 }
2838 else
2839 hdc = printer_dc;
2840
2841 points = pixels * 72.0 / GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX);
2842 if (printer_dc == NULL)
2843 ReleaseDC(hwnd, hdc);
2844
2845 return points;
2846 }
2847
2822 static int CALLBACK 2848 static int CALLBACK
2823 font_enumproc( 2849 font_enumproc(
2824 ENUMLOGFONTW *elf, 2850 ENUMLOGFONTW *elf,
2825 NEWTEXTMETRICW *ntm UNUSED, 2851 NEWTEXTMETRICW *ntm UNUSED,
2826 DWORD type UNUSED, 2852 DWORD type UNUSED,
2885 lf->lfStrikeOut = FALSE; 2911 lf->lfStrikeOut = FALSE;
2886 lf->lfWeight = FW_NORMAL; 2912 lf->lfWeight = FW_NORMAL;
2887 2913
2888 // Return success 2914 // Return success
2889 return OK; 2915 return OK;
2916 }
2917
2918 /*
2919 * Call back for EnumFontFamiliesW in expand_font_enumproc.
2920 *
2921 */
2922 static int CALLBACK
2923 expand_font_enumproc(
2924 ENUMLOGFONTW *elf,
2925 NEWTEXTMETRICW *ntm UNUSED,
2926 DWORD type UNUSED,
2927 LPARAM lparam)
2928 {
2929 LOGFONTW *lf = (LOGFONTW*)elf;
2930
2931 # ifndef FEAT_PROPORTIONAL_FONTS
2932 // Ignore non-monospace fonts without further ado
2933 if ((ntm->tmPitchAndFamily & 1) != 0)
2934 return 1;
2935 # endif
2936
2937 // Filter only on ANSI. Otherwise will see a lot of random fonts that we
2938 // usually don't want.
2939 if (lf->lfCharSet != ANSI_CHARSET)
2940 return 1;
2941
2942 int (*add_match)(char_u *) = (int (*)(char_u *))lparam;
2943
2944 WCHAR *faceNameW = lf->lfFaceName;
2945 char_u *faceName = utf16_to_enc(faceNameW, NULL);
2946 if (!faceName)
2947 return 0;
2948
2949 add_match(faceName);
2950 vim_free(faceName);
2951
2952 return 1;
2953 }
2954
2955 /*
2956 * Cmdline expansion for setting 'guifont'. Will enumerate through all
2957 * monospace fonts for completion. If used after ':', will expand to possible
2958 * font configuration options like font sizes.
2959 *
2960 * This function has "gui" in its name because in some platforms (GTK) font
2961 * handling is done by the GUI code, whereas in Windows it's part of the
2962 * platform code.
2963 */
2964 void
2965 gui_mch_expand_font(optexpand_T *args, void *param UNUSED, int (*add_match)(char_u *val))
2966 {
2967 expand_T *xp = args->oe_xp;
2968 if (xp->xp_pattern > args->oe_set_arg && *(xp->xp_pattern-1) == ':')
2969 {
2970 char buf[30];
2971
2972 // Always fill in with the current font size as first option for
2973 // convenience. We simply round to the closest integer for simplicity.
2974 int font_height = (int)round(
2975 pixels_to_points(-current_font_height, TRUE, (long_i)NULL));
2976 vim_snprintf(buf, ARRAY_LENGTH(buf), "h%d", font_height);
2977 add_match((char_u *)buf);
2978
2979 // Note: Keep this in sync with get_logfont(). Don't include 'c' and
2980 // 'q' as we fill in all the values below.
2981 static char *(p_gfn_win_opt_values[]) = {
2982 "h" , "w" , "W" , "b" , "i" , "u" , "s"};
2983 for (size_t i = 0; i < ARRAY_LENGTH(p_gfn_win_opt_values); i++)
2984 add_match((char_u *)p_gfn_win_opt_values[i]);
2985
2986 struct charset_pair *cp;
2987 for (cp = charset_pairs; cp->name != NULL; ++cp)
2988 {
2989 vim_snprintf(buf, ARRAY_LENGTH(buf), "c%s", cp->name);
2990 add_match((char_u *)buf);
2991 }
2992 struct quality_pair *qp;
2993 for (qp = quality_pairs; qp->name != NULL; ++qp)
2994 {
2995 vim_snprintf(buf, ARRAY_LENGTH(buf), "q%s", qp->name);
2996 add_match((char_u *)buf);
2997 }
2998 return;
2999 }
3000
3001 HWND hwnd = GetDesktopWindow();
3002 HDC hdc = GetWindowDC(hwnd);
3003
3004 EnumFontFamiliesW(hdc,
3005 NULL,
3006 (FONTENUMPROCW)expand_font_enumproc,
3007 (LPARAM)add_match);
3008
3009 ReleaseDC(hwnd, hdc);
2890 } 3010 }
2891 3011
2892 /* 3012 /*
2893 * Compare a UTF-16 string and an ASCII string literally. 3013 * Compare a UTF-16 string and an ASCII string literally.
2894 * Only works all the code points are inside ASCII range. 3014 * Only works all the code points are inside ASCII range.
2993 // Set the values found after ':' 3113 // Set the values found after ':'
2994 while (*p) 3114 while (*p)
2995 { 3115 {
2996 switch (*p++) 3116 switch (*p++)
2997 { 3117 {
3118 // Note: Keep this in sync with gui_mch_expand_font().
2998 case L'h': 3119 case L'h':
2999 lf->lfHeight = - points_to_pixels(p, &p, TRUE, (long_i)printer_dc); 3120 lf->lfHeight = - points_to_pixels(p, &p, TRUE, (long_i)printer_dc);
3000 break; 3121 break;
3001 case L'w': 3122 case L'w':
3002 lf->lfWidth = points_to_pixels(p, &p, FALSE, (long_i)printer_dc); 3123 lf->lfWidth = points_to_pixels(p, &p, FALSE, (long_i)printer_dc);