mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 8.1.1081: MS-Windows: cannot use some fonts
Problem: MS-Windows: cannot use fonts whose name cannot be represented in the current code page. Solution: Use wide font functions. (Ken Takata, closes #4000)
This commit is contained in:
140
src/os_mswin.c
140
src/os_mswin.c
@@ -85,7 +85,7 @@ typedef int COLORREF;
|
||||
typedef int CONSOLE_CURSOR_INFO;
|
||||
typedef int COORD;
|
||||
typedef int DWORD;
|
||||
typedef int ENUMLOGFONT;
|
||||
typedef int ENUMLOGFONTW;
|
||||
typedef int HANDLE;
|
||||
typedef int HDC;
|
||||
typedef int HFONT;
|
||||
@@ -93,7 +93,7 @@ typedef int HICON;
|
||||
typedef int HWND;
|
||||
typedef int INPUT_RECORD;
|
||||
typedef int KEY_EVENT_RECORD;
|
||||
typedef int LOGFONT;
|
||||
typedef int LOGFONTW;
|
||||
typedef int LPARAM;
|
||||
typedef int LPBOOL;
|
||||
typedef int LPCSTR;
|
||||
@@ -103,7 +103,7 @@ typedef int LPTSTR;
|
||||
typedef int LPWSTR;
|
||||
typedef int LRESULT;
|
||||
typedef int MOUSE_EVENT_RECORD;
|
||||
typedef int NEWTEXTMETRIC;
|
||||
typedef int NEWTEXTMETRICW;
|
||||
typedef int PACL;
|
||||
typedef int PRINTDLG;
|
||||
typedef int PSECURITY_DESCRIPTOR;
|
||||
@@ -1420,7 +1420,7 @@ mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
|
||||
static int stored_nCopies = 1;
|
||||
static int stored_nFlags = 0;
|
||||
|
||||
LOGFONT fLogFont;
|
||||
LOGFONTW fLogFont;
|
||||
int pifItalic;
|
||||
int pifBold;
|
||||
int pifUnderline;
|
||||
@@ -1577,7 +1577,7 @@ mch_print_init(prt_settings_T *psettings, char_u *jobname, int forceit)
|
||||
fLogFont.lfItalic = pifItalic;
|
||||
fLogFont.lfUnderline = pifUnderline;
|
||||
prt_font_handles[pifBold][pifItalic][pifUnderline]
|
||||
= CreateFontIndirect(&fLogFont);
|
||||
= CreateFontIndirectW(&fLogFont);
|
||||
}
|
||||
|
||||
SetBkMode(prt_dlg.hDC, OPAQUE);
|
||||
@@ -2915,12 +2915,12 @@ quality_id2name(DWORD id)
|
||||
return qp->name;
|
||||
}
|
||||
|
||||
static const LOGFONT s_lfDefault =
|
||||
static const LOGFONTW s_lfDefault =
|
||||
{
|
||||
-12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
|
||||
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||
PROOF_QUALITY, FIXED_PITCH | FF_DONTCARE,
|
||||
"Fixedsys" /* see _ReadVimIni */
|
||||
L"Fixedsys" /* see _ReadVimIni */
|
||||
};
|
||||
|
||||
/* Initialise the "current height" to -12 (same as s_lfDefault) just
|
||||
@@ -2937,7 +2937,7 @@ int current_font_height = -12; /* also used in gui_w48.c */
|
||||
* calculation is for a vertical (height) size or a horizontal (width) one.
|
||||
*/
|
||||
static int
|
||||
points_to_pixels(char_u *str, char_u **end, int vertical, long_i pprinter_dc)
|
||||
points_to_pixels(WCHAR *str, WCHAR **end, int vertical, long_i pprinter_dc)
|
||||
{
|
||||
int pixels;
|
||||
int points = 0;
|
||||
@@ -2948,7 +2948,7 @@ points_to_pixels(char_u *str, char_u **end, int vertical, long_i pprinter_dc)
|
||||
|
||||
while (*str != NUL)
|
||||
{
|
||||
if (*str == '.' && divisor == 0)
|
||||
if (*str == L'.' && divisor == 0)
|
||||
{
|
||||
/* Start keeping a divisor, for later */
|
||||
divisor = 1;
|
||||
@@ -2959,7 +2959,7 @@ points_to_pixels(char_u *str, char_u **end, int vertical, long_i pprinter_dc)
|
||||
break;
|
||||
|
||||
points *= 10;
|
||||
points += *str - '0';
|
||||
points += *str - L'0';
|
||||
divisor *= 10;
|
||||
}
|
||||
++str;
|
||||
@@ -2989,15 +2989,15 @@ points_to_pixels(char_u *str, char_u **end, int vertical, long_i pprinter_dc)
|
||||
|
||||
static int CALLBACK
|
||||
font_enumproc(
|
||||
ENUMLOGFONT *elf,
|
||||
NEWTEXTMETRIC *ntm UNUSED,
|
||||
int type UNUSED,
|
||||
ENUMLOGFONTW *elf,
|
||||
NEWTEXTMETRICW *ntm UNUSED,
|
||||
DWORD type UNUSED,
|
||||
LPARAM lparam)
|
||||
{
|
||||
/* Return value:
|
||||
* 0 = terminate now (monospace & ANSI)
|
||||
* 1 = continue, still no luck...
|
||||
* 2 = continue, but we have an acceptable LOGFONT
|
||||
* 2 = continue, but we have an acceptable LOGFONTW
|
||||
* (monospace, not ANSI)
|
||||
* We use these values, as EnumFontFamilies returns 1 if the
|
||||
* callback function is never called. So, we check the return as
|
||||
@@ -3005,7 +3005,7 @@ font_enumproc(
|
||||
* It's not pretty, but it works!
|
||||
*/
|
||||
|
||||
LOGFONT *lf = (LOGFONT *)(lparam);
|
||||
LOGFONTW *lf = (LOGFONTW *)(lparam);
|
||||
|
||||
#ifndef FEAT_PROPORTIONAL_FONTS
|
||||
/* Ignore non-monospace fonts without further ado */
|
||||
@@ -3013,7 +3013,7 @@ font_enumproc(
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
/* Remember this LOGFONT as a "possible" */
|
||||
/* Remember this LOGFONTW as a "possible" */
|
||||
*lf = elf->elfLogFont;
|
||||
|
||||
/* Terminate the scan as soon as we find an ANSI font */
|
||||
@@ -3027,15 +3027,15 @@ font_enumproc(
|
||||
}
|
||||
|
||||
static int
|
||||
init_logfont(LOGFONT *lf)
|
||||
init_logfont(LOGFONTW *lf)
|
||||
{
|
||||
int n;
|
||||
HWND hwnd = GetDesktopWindow();
|
||||
HDC hdc = GetWindowDC(hwnd);
|
||||
|
||||
n = EnumFontFamilies(hdc,
|
||||
(LPCSTR)lf->lfFaceName,
|
||||
(FONTENUMPROC)font_enumproc,
|
||||
n = EnumFontFamiliesW(hdc,
|
||||
lf->lfFaceName,
|
||||
(FONTENUMPROCW)font_enumproc,
|
||||
(LPARAM)lf);
|
||||
|
||||
ReleaseDC(hwnd, hdc);
|
||||
@@ -3044,7 +3044,7 @@ init_logfont(LOGFONT *lf)
|
||||
if (n == 1)
|
||||
return FAIL;
|
||||
|
||||
/* Tidy up the rest of the LOGFONT structure. We set to a basic
|
||||
/* Tidy up the rest of the LOGFONTW structure. We set to a basic
|
||||
* font - get_logfont() sets bold, italic, etc based on the user's
|
||||
* input.
|
||||
*/
|
||||
@@ -3059,40 +3059,52 @@ init_logfont(LOGFONT *lf)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare a UTF-16 string and an ASCII string literally.
|
||||
* Only works all the code points are inside ASCII range.
|
||||
*/
|
||||
static int
|
||||
utf16ascncmp(const WCHAR *w, const char *p, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (w[i] == 0 || w[i] != p[i])
|
||||
return w[i] - p[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get font info from "name" into logfont "lf".
|
||||
* Return OK for a valid name, FAIL otherwise.
|
||||
*/
|
||||
int
|
||||
get_logfont(
|
||||
LOGFONT *lf,
|
||||
LOGFONTW *lf,
|
||||
char_u *name,
|
||||
HDC printer_dc,
|
||||
int verbose)
|
||||
{
|
||||
char_u *p;
|
||||
WCHAR *p;
|
||||
int i;
|
||||
int ret = FAIL;
|
||||
static LOGFONT *lastlf = NULL;
|
||||
char_u *acpname = NULL;
|
||||
static LOGFONTW *lastlf = NULL;
|
||||
WCHAR *wname;
|
||||
|
||||
*lf = s_lfDefault;
|
||||
if (name == NULL)
|
||||
return OK;
|
||||
|
||||
/* Convert 'name' from 'encoding' to the current codepage, because
|
||||
* lf->lfFaceName uses the current codepage.
|
||||
* TODO: Use Wide APIs instead of ANSI APIs. */
|
||||
if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
|
||||
{
|
||||
int len;
|
||||
enc_to_acp(name, (int)STRLEN(name), &acpname, &len);
|
||||
name = acpname;
|
||||
}
|
||||
if (STRCMP(name, "*") == 0)
|
||||
wname = enc_to_utf16(name, NULL);
|
||||
if (wname == NULL)
|
||||
return FAIL;
|
||||
|
||||
if (wcscmp(wname, L"*") == 0)
|
||||
{
|
||||
#if defined(FEAT_GUI_MSWIN)
|
||||
CHOOSEFONT cf;
|
||||
CHOOSEFONTW cf;
|
||||
/* if name is "*", bring up std font dialog: */
|
||||
vim_memset(&cf, 0, sizeof(cf));
|
||||
cf.lStructSize = sizeof(cf);
|
||||
@@ -3102,7 +3114,7 @@ get_logfont(
|
||||
*lf = *lastlf;
|
||||
cf.lpLogFont = lf;
|
||||
cf.nFontType = 0 ; //REGULAR_FONTTYPE;
|
||||
if (ChooseFont(&cf))
|
||||
if (ChooseFontW(&cf))
|
||||
ret = OK;
|
||||
#endif
|
||||
goto theend;
|
||||
@@ -3111,14 +3123,14 @@ get_logfont(
|
||||
/*
|
||||
* Split name up, it could be <name>:h<height>:w<width> etc.
|
||||
*/
|
||||
for (p = name; *p && *p != ':'; p++)
|
||||
for (p = wname; *p && *p != L':'; p++)
|
||||
{
|
||||
if (p - name + 1 >= LF_FACESIZE)
|
||||
if (p - wname + 1 >= LF_FACESIZE)
|
||||
goto theend; /* Name too long */
|
||||
lf->lfFaceName[p - name] = *p;
|
||||
lf->lfFaceName[p - wname] = *p;
|
||||
}
|
||||
if (p != name)
|
||||
lf->lfFaceName[p - name] = NUL;
|
||||
if (p != wname)
|
||||
lf->lfFaceName[p - wname] = NUL;
|
||||
|
||||
/* First set defaults */
|
||||
lf->lfHeight = -12;
|
||||
@@ -3136,18 +3148,16 @@ get_logfont(
|
||||
int did_replace = FALSE;
|
||||
|
||||
for (i = 0; lf->lfFaceName[i]; ++i)
|
||||
if (IsDBCSLeadByte(lf->lfFaceName[i]))
|
||||
++i;
|
||||
else if (lf->lfFaceName[i] == '_')
|
||||
if (lf->lfFaceName[i] == L'_')
|
||||
{
|
||||
lf->lfFaceName[i] = ' ';
|
||||
lf->lfFaceName[i] = L' ';
|
||||
did_replace = TRUE;
|
||||
}
|
||||
if (!did_replace || init_logfont(lf) == FAIL)
|
||||
goto theend;
|
||||
}
|
||||
|
||||
while (*p == ':')
|
||||
while (*p == L':')
|
||||
p++;
|
||||
|
||||
/* Set the values found after ':' */
|
||||
@@ -3155,30 +3165,30 @@ get_logfont(
|
||||
{
|
||||
switch (*p++)
|
||||
{
|
||||
case 'h':
|
||||
case L'h':
|
||||
lf->lfHeight = - points_to_pixels(p, &p, TRUE, (long_i)printer_dc);
|
||||
break;
|
||||
case 'w':
|
||||
case L'w':
|
||||
lf->lfWidth = points_to_pixels(p, &p, FALSE, (long_i)printer_dc);
|
||||
break;
|
||||
case 'b':
|
||||
case L'b':
|
||||
lf->lfWeight = FW_BOLD;
|
||||
break;
|
||||
case 'i':
|
||||
case L'i':
|
||||
lf->lfItalic = TRUE;
|
||||
break;
|
||||
case 'u':
|
||||
case L'u':
|
||||
lf->lfUnderline = TRUE;
|
||||
break;
|
||||
case 's':
|
||||
case L's':
|
||||
lf->lfStrikeOut = TRUE;
|
||||
break;
|
||||
case 'c':
|
||||
case L'c':
|
||||
{
|
||||
struct charset_pair *cp;
|
||||
|
||||
for (cp = charset_pairs; cp->name != NULL; ++cp)
|
||||
if (STRNCMP(p, cp->name, strlen(cp->name)) == 0)
|
||||
if (utf16ascncmp(p, cp->name, strlen(cp->name)) == 0)
|
||||
{
|
||||
lf->lfCharSet = cp->charset;
|
||||
p += strlen(cp->name);
|
||||
@@ -3186,17 +3196,19 @@ get_logfont(
|
||||
}
|
||||
if (cp->name == NULL && verbose)
|
||||
{
|
||||
semsg(_("E244: Illegal charset name \"%s\" in font name \"%s\""), p, name);
|
||||
char_u *s = utf16_to_enc(p, NULL);
|
||||
semsg(_("E244: Illegal charset name \"%s\" in font name \"%s\""), s, name);
|
||||
vim_free(s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'q':
|
||||
case L'q':
|
||||
{
|
||||
struct quality_pair *qp;
|
||||
|
||||
for (qp = quality_pairs; qp->name != NULL; ++qp)
|
||||
if (STRNCMP(p, qp->name, strlen(qp->name)) == 0)
|
||||
if (utf16ascncmp(p, qp->name, strlen(qp->name)) == 0)
|
||||
{
|
||||
lf->lfQuality = qp->quality;
|
||||
p += strlen(qp->name);
|
||||
@@ -3204,7 +3216,9 @@ get_logfont(
|
||||
}
|
||||
if (qp->name == NULL && verbose)
|
||||
{
|
||||
semsg(_("E244: Illegal quality name \"%s\" in font name \"%s\""), p, name);
|
||||
char_u *s = utf16_to_enc(p, NULL);
|
||||
semsg(_("E244: Illegal quality name \"%s\" in font name \"%s\""), s, name);
|
||||
vim_free(s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -3214,7 +3228,7 @@ get_logfont(
|
||||
semsg(_("E245: Illegal char '%c' in font name \"%s\""), p[-1], name);
|
||||
goto theend;
|
||||
}
|
||||
while (*p == ':')
|
||||
while (*p == L':')
|
||||
p++;
|
||||
}
|
||||
ret = OK;
|
||||
@@ -3224,11 +3238,11 @@ theend:
|
||||
if (ret == OK && printer_dc == NULL)
|
||||
{
|
||||
vim_free(lastlf);
|
||||
lastlf = (LOGFONT *)alloc(sizeof(LOGFONT));
|
||||
lastlf = (LOGFONTW *)alloc(sizeof(LOGFONTW));
|
||||
if (lastlf != NULL)
|
||||
mch_memmove(lastlf, lf, sizeof(LOGFONT));
|
||||
mch_memmove(lastlf, lf, sizeof(LOGFONTW));
|
||||
}
|
||||
vim_free(acpname);
|
||||
vim_free(wname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user