📄 gui_w32.c
字号:
{
SCROLLINFO info;
scroll_shift = 0;
while (max > 32767)
{
max = max + 1 >> 1;
val >>= 1;
size >>= 1;
++scroll_shift;
}
if (scroll_shift > 0)
++size;
info.cbSize = sizeof(info);
info.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
info.nPos = val;
info.nMin = 0;
info.nMax = max;
info.nPage = size;
SetScrollInfo(sb->id, SB_CTL, &info, TRUE);
}
void
gui_mch_set_scrollbar_pos(
GuiScrollbar *sb,
int x,
int y,
int w,
int h)
{
SetWindowPos(sb->id, NULL, x, y, w, h, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
}
void
gui_mch_create_scrollbar(
GuiScrollbar *sb,
int orient) /* SBAR_VERT or SBAR_HORIZ */
{
sb->id = CreateWindow(
"SCROLLBAR", "Scrollbar",
WS_CHILD | ((orient == SBAR_VERT) ? SBS_VERT : SBS_HORZ), 0, 0,
10, /* Any value will do for now */
10, /* Any value will do for now */
s_hwnd, NULL,
s_hinst, NULL);
}
void
gui_mch_destroy_scrollbar(GuiScrollbar *sb)
{
DestroyWindow(sb->id);
}
/*
* Get the character size of a font, by measuring the size of four characters.
*/
static void
GetFontSize(GuiFont font)
{
HWND hwnd = GetDesktopWindow();
HDC hdc = GetWindowDC(hwnd);
HFONT hfntOld = SelectFont(hdc, (HFONT)font);
TEXTMETRIC tm;
/*
static const char ach[] = {'W', 'f', 'g', 'M'};
SIZE siz;
GetTextExtentPoint(hdc, ach, sizeof(ach), &siz);
*/
GetTextMetrics(hdc, &tm);
gui.char_width = tm.tmAveCharWidth + tm.tmOverhang;
/*
* Make characters one pixel higher, so that italic and bold fonts don't
* draw off the bottom of their character space. Also means that we can
* underline an underscore for normal text.
*/
gui.char_height = tm.tmHeight+1; /*siz.cy + 1;*/
/* TRACE("GetFontSize: h %d, w %d\n", gui.char_height, gui.char_width); */
SelectFont(hdc, hfntOld);
ReleaseDC(hwnd, hdc);
}
static GuiFont
get_font_handle(LOGFONT *lf)
{
HFONT *font = NULL;
/* Load the font */
font = CreateFontIndirect(lf);
if (font == NULL)
return (GuiFont)0;
return (GuiFont)font;
}
/* Convert a string representing a point size into pixels. The string should
* be a positive decimal number, with an optional decimal point (eg, "12", or
* "10.5"). The pixel value is returned, and a pointer to the next unconverted
* character is stored in *end. The flag "vertical" says whether this
* 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)
{
int pixels;
int points = 0;
int divisor = 0;
HWND hwnd;
HDC hdc;
while (*str)
{
if (*str == '.' && divisor == 0)
{
/* Start keeping a divisor, for later */
divisor = 1;
continue;
}
if (!isdigit(*str))
break;
points *= 10;
points += *str - '0';
divisor *= 10;
++str;
}
if (divisor == 0)
divisor = 1;
hwnd = GetDesktopWindow();
hdc = GetWindowDC(hwnd);
pixels = MulDiv(points,
GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX),
72 * divisor);
ReleaseDC(hwnd, hdc);
*end = str;
return pixels;
}
static int
pixels_to_points(int pixels, int vertical)
{
int points;
HWND hwnd;
HDC hdc;
hwnd = GetDesktopWindow();
hdc = GetWindowDC(hwnd);
points = MulDiv(pixels, 72,
GetDeviceCaps(hdc, vertical ? LOGPIXELSY : LOGPIXELSX));
ReleaseDC(hwnd, hdc);
return points;
}
static int CALLBACK
font_enumproc(
ENUMLOGFONT *elf,
NEWTEXTMETRIC *ntm,
int type,
LPARAM lparam)
{
/* Return value:
* 0 = terminate now (monospace & ANSI)
* 1 = continue, still no luck...
* 2 = continue, but we have an acceptable LOGFONT
* (monospace, not ANSI)
* We use these values, as EnumFontFamilies returns 1 if the
* callback function is never called. So, we check the return as
* 0 = perfect, 2 = OK, 1 = no good...
* It's not pretty, but it works!
*/
LOGFONT *lf = (LOGFONT *)(lparam);
/* Ignore non-monospace fonts without further ado */
if ((ntm->tmPitchAndFamily & 1) != 0)
return 1;
/* Remember this LOGFONT as a "possible" */
*lf = elf->elfLogFont;
/* Terminate the scan as soon as we find an ANSI font */
if (lf->lfCharSet == ANSI_CHARSET
|| lf->lfCharSet == OEM_CHARSET
|| lf->lfCharSet == DEFAULT_CHARSET)
return 0;
/* Continue the scan - we have a non-ANSI font */
return 2;
}
static int
init_logfont(LOGFONT *lf)
{
int n;
HWND hwnd = GetDesktopWindow();
HDC hdc = GetWindowDC(hwnd);
n = EnumFontFamilies(hdc,
lf->lfFaceName,
(FONTENUMPROC)font_enumproc,
(LPARAM)(lf));
ReleaseDC(hwnd, hdc);
/* If we couldn't find a useable font, return failure */
if (n == 1)
return FAIL;
/* Tidy up the rest of the LOGFONT structure. We set to a basic
* font - get_logfont() sets bold, italic, etc based on the user's
* input.
*/
lf->lfHeight = current_font_height;
lf->lfWidth = 0;
lf->lfItalic = FALSE;
lf->lfUnderline = FALSE;
lf->lfStrikeOut = FALSE;
lf->lfWeight = FW_NORMAL;
/* Return success */
return OK;
}
static int
get_logfont(
LOGFONT *lf,
char_u *name)
{
char_u *p;
CHOOSEFONT cf;
int i;
static LOGFONT *lastlf = NULL;
*lf = s_lfDefault;
if (name == NULL)
return 1;
if (STRCMP(name, "*") == 0)
{
/* ron: if name is "*", bring up std font dialog: */
memset(&cf, 0, sizeof(cf));
cf.lStructSize = sizeof(cf);
cf.hwndOwner = s_hwnd;
cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_INITTOLOGFONTSTRUCT;
if (lastlf != NULL)
*lf = *lastlf;
cf.lpLogFont = lf;
cf.nFontType = 0 ; //REGULAR_FONTTYPE;
if (ChooseFont(&cf))
goto theend;
}
/*
* Split name up, it could be <name>:h<height>:w<width> etc.
*/
for (p = name; *p && *p != ':'; p++)
{
if (p - name + 1 > LF_FACESIZE)
return 0; /* Name too long */
lf->lfFaceName[p - name] = *p;
}
if (p != name)
lf->lfFaceName[p - name] = NUL;
/* First set defaults */
lf->lfHeight = -12;
lf->lfWidth = 0;
lf->lfWeight = FW_NORMAL;
lf->lfItalic = FALSE;
lf->lfUnderline = FALSE;
lf->lfStrikeOut = FALSE;
/*
* If the font can't be found, try replacing '_' by ' '.
*/
if (init_logfont(lf) == FAIL)
{
int did_replace = FALSE;
for (i = 0; lf->lfFaceName[i]; ++i)
if (lf->lfFaceName[i] == '_')
{
lf->lfFaceName[i] = ' ';
did_replace = TRUE;
}
if (!did_replace || init_logfont(lf) == FAIL)
return 0;
}
while (*p == ':')
p++;
/* Set the values found after ':' */
while (*p)
{
switch (*p++)
{
case 'h':
lf->lfHeight = - points_to_pixels(p, &p, TRUE);
break;
case 'w':
lf->lfWidth = points_to_pixels(p, &p, FALSE);
break;
case 'b':
lf->lfWeight = FW_BOLD;
break;
case 'i':
lf->lfItalic = TRUE;
break;
case 'u':
lf->lfUnderline = TRUE;
break;
case 's':
lf->lfStrikeOut = TRUE;
break;
default:
sprintf((char *)IObuff,
"Illegal char '%c' in font name \"%s\"",
p[-1], name);
EMSG(IObuff);
break;
}
while (*p == ':')
p++;
}
theend:
/* ron: init lastlf */
vim_free(lastlf);
lastlf = (LOGFONT *)alloc(sizeof(LOGFONT));
if (lastlf != NULL)
mch_memmove(lastlf, lf, sizeof(LOGFONT));
return 1;
}
/*
* Initialise vim to use the font with the given name. Return FAIL if the font
* could not be loaded, OK otherwise.
*/
int
gui_mch_init_font(char_u *font_name)
{
LOGFONT lf;
GuiFont font = (GuiFont)0;
char *p;
/* Load the font */
if (get_logfont(&lf, font_name))
font = get_font_handle(&lf);
if (font == (GuiFont)0)
return FAIL;
if (font_name == NULL)
font_name = lf.lfFaceName;
gui_mch_free_font(gui.norm_font);
gui.norm_font = font;
current_font_height = lf.lfHeight;
GetFontSize(font);
hl_set_font_name(lf.lfFaceName);
if (STRCMP(font_name, "*") == 0)
{
p = alloc((unsigned)(strlen(lf.lfFaceName) + 10));
if (p != NULL)
{
/* make a normal font string out of the lf thing:*/
sprintf(p, "%s:h%d", lf.lfFaceName, pixels_to_points(
lf.lfHeight < 0 ? -lf.lfHeight : lf.lfHeight, TRUE));
vim_free(p_guifont);
p_guifont = p;
while (*p)
{
if (*p == ' ')
*p = '_';
++p;
}
}
}
if (!lf.lfItalic)
{
lf.lfItalic = TRUE;
gui.ital_font = get_font_handle(&lf);
lf.lfItalic = FALSE;
}
if (lf.lfWeight < FW_BOLD)
{
lf.lfWeight = FW_BOLD;
gui.bold_font = get_font_handle(&lf);
if (!lf.lfItalic)
{
lf.lfItalic = TRUE;
gui.boldital_font = get_font_handle(&lf);
}
}
return OK;
}
GuiFont
gui_mch_get_font(
char_u *name,
int giveErrorIfMissing)
{
LOGFONT lf;
GuiFont font;
get_logfont(&lf, name);
font = get_font_handle(&lf);
if (font == (GuiFont)0 && giveErrorIfMissing)
EMSG2("Unknown font: %s", name);
return font;
}
/*
* Set the current text font.
*/
void
gui_mch_set_font(GuiFont font)
{
gui.currFont = font;
}
/*
* Return TRUE if the two fonts given are equivalent.
*/
int
gui_mch_same_font(
GuiFont f1,
GuiFont f2)
{
return f1 == f2;
}
void
gui_mch_free_font(GuiFont font)
{
if (font)
DeleteObject((HFONT)font);
}
static int
hex_digit(int c)
{
if (vim_isdigit(c))
return c - '0';
c = TO_LOWER(c);
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return -1000;
}
/*
* Return the Pixel value (color) for the given color name.
* Return -1 for error.
*/
GuiColor
gui_mch_get_color(char_u *name)
{
typedef struct GuiColorTable
{
char *name;
COLORREF color;
} GuiColorTable;
static GuiColorTable table[] =
{
{"Black", RGB(0x00, 0x00, 0x00)},
{"DarkGray", RGB(0x80, 0x80, 0x80)},
{"DarkGrey", RGB(0x80, 0x80, 0x80)},
{"Gray", RGB(0xC0, 0xC0, 0xC0)},
{"Grey", RGB(0xC0, 0xC0, 0xC0)},
{"LightGray", RGB(0xE0, 0xE0, 0xE0)},
{"LightGrey", RGB(0xE0, 0xE0, 0xE0)},
{"White", RGB(0xFF, 0xFF, 0xFF)},
{"DarkRed", RGB(0x80, 0x00, 0x00)},
{"Red", RGB(0xFF, 0x00, 0x00)},
{"LightRed", RGB(0xFF, 0xA0, 0xA0)},
{"DarkBlue", RGB(0x00, 0x00, 0x80)},
{"Blue", RGB(0x00, 0x00, 0xFF)},
{"LightBlue", RGB(0xA0, 0xA0, 0xFF)},
{"DarkGreen", RGB(0x00, 0x80, 0x00)},
{"Green", RGB(0x00, 0xFF, 0x00)},
{"LightGreen", RGB(0xA0, 0xFF, 0xA0)},
{"DarkCyan", RGB(0x00, 0x80, 0x80)},
{"Cyan", RGB(0x00, 0xFF, 0xFF)},
{"LightCyan", RGB(0xA0, 0xFF, 0xFF)},
{"DarkMagenta", RGB(0x80, 0x00, 0x80)},
{"Magenta", RGB(0xFF, 0x00, 0xFF)},
{"LightMagenta", RGB(0xFF, 0xA0, 0xFF)},
{"Brown", RGB(0x80, 0x40, 0x40)},
{"Yellow", RGB(0xFF, 0xFF, 0x00)},
{"LightYellow", RGB(0xFF, 0xFF, 0xA0)},
{"SeaGreen", RGB(0x2E, 0x8B, 0x57)},
{"Orange", RGB(0xFF, 0xA5, 0x00)},
{"Purple", RGB(0xA0, 0x20, 0xF0)},
{"SlateBlue", RGB(0x6A, 0x5A, 0xCD)},
{"Violet", RGB(0xEE, 0x82, 0xEE)},
};
typedef struct SysColorTable
{
char *name;
int color;
} SysColorTable;
static SysColorTable sys_table[] =
{
"SYS_3DDKSHADOW", COLOR_3DDKSHADOW,
"SYS_3DFACE", COLOR_3DFACE,
"SYS_BTNFACE", COLOR_BTNFACE,
"SYS_3DHILIGHT", COLOR_3DHILIGHT,
"SYS_3DHIGHLIGHT", COLOR_3DHIGHLIGHT,
"SYS_BTNHILIGHT", COLOR_BTNHILIGHT,
"SYS_BTNHIGHLIGHT", COLOR_BTNHIGHLIGH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -