diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-03-30 16:24:16 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-03-30 16:24:16 +0100 |
commit | 433a5eb9de861dd01ea3b3dfa3b8fe23527cab54 (patch) | |
tree | 8ca2584bcc3dfce7f1a19c06f0346439695a2cda /src/os_mswin.c | |
parent | ef7f0e367eeaf6fb31b1caa0e3de1a4b07e86af3 (diff) | |
download | vim-git-433a5eb9de861dd01ea3b3dfa3b8fe23527cab54.tar.gz |
patch 8.1.1081: MS-Windows: cannot use some fontsv8.1.1081
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)
Diffstat (limited to 'src/os_mswin.c')
-rw-r--r-- | src/os_mswin.c | 140 |
1 files changed, 77 insertions, 63 deletions
diff --git a/src/os_mswin.c b/src/os_mswin.c index 27a2cc6ac..ad5b60fd8 100644 --- a/src/os_mswin.c +++ b/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. */ @@ -3060,39 +3060,51 @@ init_logfont(LOGFONT *lf) } /* + * 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; } |