📄 msw_style.c
字号:
/* MS-Windows Engine (aka GTK-Wimp) * * Copyright (C) 2003, 2004 Raymond Penners <raymond@dotsphinx.com> * Includes code adapted from redmond95 by Owen Taylor, and * gtk-nativewin by Evan Martin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Useful resources: * * http://lxr.mozilla.org/mozilla/source/gfx/src/windows/nsNativeThemeWin.cpp * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/functions/drawthemebackground.asp */#include "msw_style.h"#include "xp_theme.h"#include <windows.h>#include <math.h>#include <string.h>#include <stdio.h>#include "gtk/gtk.h"#include "gtk/gtk.h"#include "gdk/win32/gdkwin32.h"/* Default values, not normally used */static const GtkRequisition default_option_indicator_size = { 9, 8 };static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };static GtkStyleClass *parent_class;typedef enum { CHECK_AA, CHECK_BASE, CHECK_BLACK, CHECK_DARK, CHECK_LIGHT, CHECK_MID, CHECK_TEXT, RADIO_BASE, RADIO_BLACK, RADIO_DARK, RADIO_LIGHT, RADIO_MID, RADIO_TEXT} Part;#define PART_SIZE 13static const char check_aa_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};static const char check_base_bits[] = { 0x00,0x00,0x00,0x00,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc, 0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0x00,0x00,0x00,0x00};static const char check_black_bits[] = { 0x00,0x00,0xfe,0x0f,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00};static const char check_dark_bits[] = { 0xff,0x1f,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};static const char check_light_bits[] = { 0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, 0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xfe,0x1f};static const char check_mid_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0xfc,0x0f,0x00,0x00};static const char check_text_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x88,0x03,0xd8,0x01,0xf8, 0x00,0x70,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00};static const char radio_base_bits[] = { 0x00,0x00,0x00,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc, 0x07,0xfc,0x07,0xf8,0x03,0xf0,0x01,0x00,0x00,0x00,0x00};static const char radio_black_bits[] = { 0x00,0x00,0xf0,0x01,0x0c,0x02,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, 0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00};static const char radio_dark_bits[] = { 0xf0,0x01,0x0c,0x06,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, 0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00};static const char radio_light_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x10,0x00, 0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x0c,0x06,0xf0,0x01};static const char radio_mid_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x08,0x00, 0x08,0x00,0x08,0x00,0x04,0x0c,0x06,0xf0,0x01,0x00,0x00};static const char radio_text_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0x01,0xf0,0x01,0xf0, 0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};static struct { const char *bits; GdkBitmap *bmap;} parts[] = { { check_aa_bits, NULL }, { check_base_bits, NULL }, { check_black_bits, NULL }, { check_dark_bits, NULL }, { check_light_bits, NULL }, { check_mid_bits, NULL }, { check_text_bits, NULL }, { radio_base_bits, NULL }, { radio_black_bits, NULL }, { radio_dark_bits, NULL }, { radio_light_bits, NULL }, { radio_mid_bits, NULL }, { radio_text_bits, NULL }};static gbooleanget_system_font(XpThemeClass klazz, XpThemeFont type, LOGFONT *out_lf){#if 0 /* TODO: this crashes. need to figure out why and how to fix it */ if (xp_theme_get_system_font(klazz, type, out_lf)) return TRUE; else#endif { NONCLIENTMETRICS ncm; ncm.cbSize = sizeof(NONCLIENTMETRICS); if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) { if (type == XP_THEME_FONT_CAPTION) *out_lf = ncm.lfCaptionFont; else if (type == XP_THEME_FONT_MENU) *out_lf = ncm.lfMenuFont; else if (type == XP_THEME_FONT_STATUS) *out_lf = ncm.lfStatusFont; else *out_lf = ncm.lfMessageFont; return TRUE; } } return FALSE;}/***************************** BEGIN STOLEN FROM PANGO *****************************//* This code is stolen from Pango 1.4. It attempts to address the following problems: http://bugzilla.gnome.org/show_bug.cgi?id=135098 http://sourceforge.net/tracker/index.php?func=detail&aid=895762&group_id=76416&atid=547655 As Owen suggested in bug 135098, once Pango 1.6 is released, we need to get rid of this code.*/#define PING(printlist)/* TrueType defines: */#define MAKE_TT_TABLE_NAME(c1, c2, c3, c4) \ (((guint32)c4) << 24 | ((guint32)c3) << 16 | ((guint32)c2) << 8 | ((guint32)c1))#define CMAP (MAKE_TT_TABLE_NAME('c','m','a','p'))#define CMAP_HEADER_SIZE 4#define NAME (MAKE_TT_TABLE_NAME('n','a','m','e'))#define NAME_HEADER_SIZE 6#define ENCODING_TABLE_SIZE 8#define APPLE_UNICODE_PLATFORM_ID 0#define MACINTOSH_PLATFORM_ID 1#define ISO_PLATFORM_ID 2#define MICROSOFT_PLATFORM_ID 3#define SYMBOL_ENCODING_ID 0#define UNICODE_ENCODING_ID 1#define UCS4_ENCODING_ID 10struct name_header{ guint16 format_selector; guint16 num_records; guint16 string_storage_offset;};struct name_record{ guint16 platform_id; guint16 encoding_id; guint16 language_id; guint16 name_id; guint16 string_length; guint16 string_offset;};static gbooleanpango_win32_get_name_header (HDC hdc, struct name_header *header){ if (GetFontData (hdc, NAME, 0, header, sizeof (*header)) != sizeof (*header)) return FALSE; header->num_records = GUINT16_FROM_BE (header->num_records); header->string_storage_offset = GUINT16_FROM_BE (header->string_storage_offset); return TRUE;}static gbooleanpango_win32_get_name_record (HDC hdc, gint i, struct name_record *record){ if (GetFontData (hdc, NAME, 6 + i * sizeof (*record), record, sizeof (*record)) != sizeof (*record)) return FALSE; record->platform_id = GUINT16_FROM_BE (record->platform_id); record->encoding_id = GUINT16_FROM_BE (record->encoding_id); record->language_id = GUINT16_FROM_BE (record->language_id); record->name_id = GUINT16_FROM_BE (record->name_id); record->string_length = GUINT16_FROM_BE (record->string_length); record->string_offset = GUINT16_FROM_BE (record->string_offset); return TRUE;}static gchar *get_family_name (LOGFONT *lfp, HDC pango_win32_hdc){ HFONT hfont; HFONT oldhfont; struct name_header header; struct name_record record; gint unicode_ix = -1, mac_ix = -1, microsoft_ix = -1; gint name_ix; gchar *codeset; gchar *string = NULL; gchar *name; gint i, l; gsize nbytes; /* If lfFaceName is ASCII, assume it is the common (English) name * for the font. Is this valid? Do some TrueType fonts have * different names in French, German, etc, and does the system * return these if the locale is set to use French, German, etc? */ l = strlen (lfp->lfFaceName); for (i = 0; i < l; i++) if (lfp->lfFaceName[i] < ' ' || lfp->lfFaceName[i] > '~') break; if (i == l) return g_strdup (lfp->lfFaceName); if ((hfont = CreateFontIndirect (lfp)) == NULL) goto fail0; if ((oldhfont = SelectObject (pango_win32_hdc, hfont)) == NULL) goto fail1; if (!pango_win32_get_name_header (pango_win32_hdc, &header)) goto fail2; PING (("%d name records", header.num_records)); for (i = 0; i < header.num_records; i++) { if (!pango_win32_get_name_record (pango_win32_hdc, i, &record)) goto fail2; if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0) continue; PING(("platform:%d encoding:%d language:%04x name_id:%d", record.platform_id, record.encoding_id, record.language_id, record.name_id)); if (record.platform_id == APPLE_UNICODE_PLATFORM_ID || record.platform_id == ISO_PLATFORM_ID) unicode_ix = i; else if (record.platform_id == MACINTOSH_PLATFORM_ID && record.encoding_id == 0 && /* Roman */ record.language_id == 0) /* English */ mac_ix = i; else if (record.platform_id == MICROSOFT_PLATFORM_ID) if ((microsoft_ix == -1 || PRIMARYLANGID (record.language_id) == LANG_ENGLISH) && (record.encoding_id == SYMBOL_ENCODING_ID || record.encoding_id == UNICODE_ENCODING_ID || record.encoding_id == UCS4_ENCODING_ID)) microsoft_ix = i; } if (microsoft_ix >= 0) name_ix = microsoft_ix; else if (mac_ix >= 0) name_ix = mac_ix; else if (unicode_ix >= 0) name_ix = unicode_ix; else goto fail2; if (!pango_win32_get_name_record (pango_win32_hdc, name_ix, &record)) goto fail2; string = g_malloc (record.string_length + 1); if (GetFontData (pango_win32_hdc, NAME, header.string_storage_offset + record.string_offset, string, record.string_length) != record.string_length) goto fail2; string[record.string_length] = '\0'; if (name_ix == microsoft_ix) if (record.encoding_id == SYMBOL_ENCODING_ID || record.encoding_id == UNICODE_ENCODING_ID) codeset = "UTF-16BE"; else codeset = "UCS-4BE"; else if (name_ix == mac_ix) codeset = "MacRoman"; else /* name_ix == unicode_ix */ codeset = "UCS-4BE"; name = g_convert (string, record.string_length, "UTF-8", codeset, NULL, &nbytes, NULL); if (name == NULL) goto fail2; g_free (string); PING(("%s", name)); SelectObject (pango_win32_hdc, oldhfont); DeleteObject (hfont); return name; fail2: g_free (string); SelectObject (pango_win32_hdc, oldhfont); fail1: DeleteObject (hfont); fail0: return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);}/***************************** END STOLEN FROM PANGO *****************************/static char *sys_font_to_pango_font (XpThemeClass klazz, XpThemeFont type, char * buf, size_t bufsiz){ HDC hDC; HWND hwnd; LOGFONT lf; int pt_size; const char * weight; const char * style; char * font; if (get_system_font(klazz, type, &lf)) { switch (lf.lfWeight) { case FW_THIN: case FW_EXTRALIGHT: weight = "Ultra-Light"; break; case FW_LIGHT: weight = "Light"; break; case FW_BOLD: weight = "Bold"; break; case FW_SEMIBOLD: weight = "Semi-Bold"; break; case FW_ULTRABOLD: weight = "Ultra-Bold"; break; case FW_HEAVY: weight = "Heavy"; break; default: weight = ""; break; } if (lf.lfItalic) style="Italic"; else style=""; hwnd = GetDesktopWindow(); hDC = GetDC(hwnd); if (hDC) { pt_size = -MulDiv(lf.lfHeight, 72, GetDeviceCaps(hDC,LOGPIXELSY)); ReleaseDC(hwnd, hDC); } else pt_size = 10; font = get_family_name(&lf, hDC); g_snprintf(buf, bufsiz, "%s %s %s %d", font, style, weight, pt_size); g_free(font); return buf; } return NULL;}/* missing from ms's header files */#ifndef SPI_GETMENUSHOWDELAY#define SPI_GETMENUSHOWDELAY 106#endif/* I don't know the proper XP theme class for things like HIGHLIGHTTEXT, so we'll just define it to be "BUTTON" for now */#define XP_THEME_CLASS_TEXT XP_THEME_CLASS_BUTTONstatic voidsetup_menu_settings (GtkSettings * settings){ int menu_delay; gboolean win95 = FALSE; OSVERSIONINFOEX osvi; GObjectClass * klazz = G_OBJECT_GET_CLASS(G_OBJECT(settings)); ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if (!GetVersionEx ( (OSVERSIONINFO *) &osvi)) win95 = TRUE; /* assume the worst */ if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) win95 = TRUE; if (!win95) { if (SystemParametersInfo (SPI_GETMENUSHOWDELAY, 0, &menu_delay, 0)) { if (klazz) { if (g_object_class_find_property (klazz, "gtk-menu-bar-popup-delay")) { g_object_set (settings, "gtk-menu-bar-popup-delay", 0, NULL); } if (g_object_class_find_property (klazz, "gtk-menu-popup-delay")) { g_object_set (settings, "gtk-menu-popup-delay", menu_delay, NULL); } if (g_object_class_find_property (klazz, "gtk-menu-popdown-delay")) { g_object_set (settings, "gtk-menu-popdown-delay", menu_delay, NULL); } } } }}voidmsw_style_setup_system_settings (void){ GtkSettings * settings; int cursor_blink_time; settings = gtk_settings_get_default (); if (!settings) return; cursor_blink_time = GetCaretBlinkTime (); g_object_set (settings, "gtk-cursor-blink", cursor_blink_time > 0, NULL); if (cursor_blink_time > 0) g_object_set (settings, "gtk-cursor-blink-time", 2*cursor_blink_time, NULL); g_object_set (settings, "gtk-double-click-distance", GetSystemMetrics(SM_CXDOUBLECLK), NULL); g_object_set (settings, "gtk-double-click-time", GetDoubleClickTime(), NULL); g_object_set (settings, "gtk-dnd-drag-threshold", GetSystemMetrics(SM_CXDRAG), NULL); setup_menu_settings (settings); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -