summaryrefslogtreecommitdiff
path: root/src/w32font.c
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2011-10-28 11:54:02 +0200
committerEli Zaretskii <eliz@gnu.org>2011-10-28 11:54:02 +0200
commitdb4f02f208c551982a54f6ea1fdf3d5577572ca3 (patch)
treebd87986140b27bd15eff69e001ed00f4ee8cc18f /src/w32font.c
parent7a6c0941742d41702fb56cd492d4897e476ebc25 (diff)
downloademacs-db4f02f208c551982a54f6ea1fdf3d5577572ca3.tar.gz
Fix bug #8562 with Emacs display on Windows 9X.
Thanks to oslsachem <oslsachem@gmail.com> for helping to debug this. src/w32font.c (g_b_init_is_w9x, g_b_init_get_outline_metrics_w) (g_b_init_get_text_metrics_w, g_b_init_get_glyph_outline_w) (g_b_init_get_glyph_outline_w): New static variables. (GetOutlineTextMetricsW_Proc, GetTextMetricsW_Proc) (GetGlyphOutlineW_Proc): New typedefs. (w32_load_unicows_or_gdi32, get_outline_metrics_w) (get_text_metrics_w, get_glyph_outline_w, globals_of_w32font): New functions. (w32font_open_internal, compute_metrics): Call get_outline_metrics_w, get_text_metrics_w, and get_glyph_outline_w instead of calling the "wide" APIs directly. src/emacs.c (main) [HAVE_NTGUI]: Call globals_of_w32font. src/w32.h (syms_of_w32font): Add prototype.
Diffstat (limited to 'src/w32font.c')
-rw-r--r--src/w32font.c149
1 files changed, 145 insertions, 4 deletions
diff --git a/src/w32font.c b/src/w32font.c
index f47b7a46b1e..fb41989caa7 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -145,6 +145,137 @@ struct font_callback_data
style variations if the font name is not specified. */
static void list_all_matching_fonts (struct font_callback_data *);
+static BOOL g_b_init_is_w9x;
+static BOOL g_b_init_get_outline_metrics_w;
+static BOOL g_b_init_get_text_metrics_w;
+static BOOL g_b_init_get_glyph_outline_w;
+static BOOL g_b_init_get_glyph_outline_w;
+
+typedef UINT (WINAPI * GetOutlineTextMetricsW_Proc) (
+ HDC hdc,
+ UINT cbData,
+ LPOUTLINETEXTMETRICW lpotmw);
+typedef BOOL (WINAPI * GetTextMetricsW_Proc) (
+ HDC hdc,
+ LPTEXTMETRICW lptmw);
+typedef DWORD (WINAPI * GetGlyphOutlineW_Proc) (
+ HDC hdc,
+ UINT uChar,
+ UINT uFormat,
+ LPGLYPHMETRICS lpgm,
+ DWORD cbBuffer,
+ LPVOID lpvBuffer,
+ const MAT2 *lpmat2);
+
+/* Several "wide" functions we use to support the font backends are
+ unavailable on Windows 9X, unless UNICOWS.DLL is installed (their
+ versions in the default libraries are non-functional stubs). On NT
+ and later systems, these functions are in GDI32.DLL. The following
+ helper function attempts to load UNICOWS.DLL on Windows 9X, and
+ refuses to let Emacs start up if that library is not found. On NT
+ and later versions, it simply loads GDI32.DLL, which should always
+ be available. */
+static HMODULE
+w32_load_unicows_or_gdi32 (void)
+{
+ static BOOL is_9x = 0;
+ OSVERSIONINFO os_ver;
+ HMODULE ret;
+ if (g_b_init_is_w9x == 0)
+ {
+ g_b_init_is_w9x = 1;
+ ZeroMemory (&os_ver, sizeof (OSVERSIONINFO));
+ os_ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ if (GetVersionEx (&os_ver))
+ is_9x = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+ }
+ if (is_9x)
+ {
+ ret = LoadLibrary ("Unicows.dll");
+ if (!ret)
+ {
+ int button;
+
+ button = MessageBox (NULL,
+ "Emacs cannot load the UNICOWS.DLL library.\n"
+ "This library is essential for using Emacs\n"
+ "on this system. You need to install it.\n\n"
+ "However, you can still use Emacs by invoking\n"
+ "it with the '-nw' command-line option.\n\n"
+ "Emacs will exit when you click OK.",
+ "Emacs cannot load UNICOWS.DLL",
+ MB_ICONERROR | MB_TASKMODAL
+ | MB_SETFOREGROUND | MB_OK);
+ switch (button)
+ {
+ case IDOK:
+ default:
+ exit (1);
+ }
+ }
+ }
+ else
+ ret = LoadLibrary ("Gdi32.dll");
+}
+
+/* The following 3 functions call the problematic "wide" APIs via
+ function pointers, to avoid linking against the non-standard
+ libunicows on W9X. */
+static UINT WINAPI
+get_outline_metrics_w(HDC hdc, UINT cbData, LPOUTLINETEXTMETRICW lpotmw)
+{
+ static GetOutlineTextMetricsW_Proc s_pfn_Get_Outline_Text_MetricsW = NULL;
+ HMODULE hm_unicows = NULL;
+ if (g_b_init_get_outline_metrics_w == 0)
+ {
+ g_b_init_get_outline_metrics_w = 1;
+ hm_unicows = w32_load_unicows_or_gdi32 ();
+ if (hm_unicows)
+ s_pfn_Get_Outline_Text_MetricsW = (GetOutlineTextMetricsW_Proc)
+ GetProcAddress (hm_unicows, "GetOutlineTextMetricsW");
+ }
+ if (s_pfn_Get_Outline_Text_MetricsW == NULL)
+ abort (); /* cannot happen */
+ return s_pfn_Get_Outline_Text_MetricsW (hdc, cbData, lpotmw);
+}
+
+static BOOL WINAPI
+get_text_metrics_w(HDC hdc, LPTEXTMETRICW lptmw)
+{
+ static GetTextMetricsW_Proc s_pfn_Get_Text_MetricsW = NULL;
+ HMODULE hm_unicows = NULL;
+ if (g_b_init_get_text_metrics_w == 0)
+ {
+ g_b_init_get_text_metrics_w = 1;
+ hm_unicows = w32_load_unicows_or_gdi32 ();
+ if (hm_unicows)
+ s_pfn_Get_Text_MetricsW = (GetTextMetricsW_Proc)
+ GetProcAddress (hm_unicows, "GetTextMetricsW");
+ }
+ if (s_pfn_Get_Text_MetricsW == NULL)
+ abort (); /* cannot happen */
+ return s_pfn_Get_Text_MetricsW (hdc, lptmw);
+}
+
+static DWORD WINAPI
+get_glyph_outline_w (HDC hdc, UINT uChar, UINT uFormat, LPGLYPHMETRICS lpgm,
+ DWORD cbBuffer, LPVOID lpvBuffer, const MAT2 *lpmat2)
+{
+ static GetGlyphOutlineW_Proc s_pfn_Get_Glyph_OutlineW = NULL;
+ HMODULE hm_unicows = NULL;
+ if (g_b_init_get_glyph_outline_w == 0)
+ {
+ g_b_init_get_glyph_outline_w = 1;
+ hm_unicows = w32_load_unicows_or_gdi32 ();
+ if (hm_unicows)
+ s_pfn_Get_Glyph_OutlineW = (GetGlyphOutlineW_Proc)
+ GetProcAddress (hm_unicows, "GetGlyphOutlineW");
+ }
+ if (s_pfn_Get_Glyph_OutlineW == NULL)
+ abort (); /* cannot happen */
+ return s_pfn_Get_Glyph_OutlineW (hdc, uChar, uFormat, lpgm, cbBuffer,
+ lpvBuffer, lpmat2);
+}
static int
memq_no_quit (Lisp_Object elt, Lisp_Object list)
@@ -816,11 +947,11 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
old_font = SelectObject (dc, hfont);
/* Try getting the outline metrics (only works for truetype fonts). */
- len = GetOutlineTextMetricsW (dc, 0, NULL);
+ len = get_outline_metrics_w (dc, 0, NULL);
if (len)
{
metrics = (OUTLINETEXTMETRICW *) alloca (len);
- if (GetOutlineTextMetricsW (dc, len, metrics))
+ if (get_outline_metrics_w (dc, len, metrics))
memcpy (&w32_font->metrics, &metrics->otmTextMetrics,
sizeof (TEXTMETRICW));
else
@@ -828,7 +959,7 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
}
if (!metrics)
- GetTextMetricsW (dc, &w32_font->metrics);
+ get_text_metrics_w (dc, &w32_font->metrics);
w32_font->cached_metrics = NULL;
w32_font->n_cache_blocks = 0;
@@ -2306,7 +2437,7 @@ compute_metrics (HDC dc, struct w32font_info *w32_font, unsigned int code,
transform.eM11.value = 1;
transform.eM22.value = 1;
- if (GetGlyphOutlineW (dc, code, options, &gm, 0, NULL, &transform)
+ if (get_glyph_outline_w (dc, code, options, &gm, 0, NULL, &transform)
!= GDI_ERROR)
{
metrics->lbearing = gm.gmptGlyphOrigin.x;
@@ -2581,3 +2712,13 @@ versions of Windows) characters. */);
w32font_driver.type = Qgdi;
register_font_driver (&w32font_driver, NULL);
}
+
+void
+globals_of_w32font (void)
+{
+ g_b_init_is_w9x = 0;
+ g_b_init_get_outline_metrics_w = 0;
+ g_b_init_get_text_metrics_w = 0;
+ g_b_init_get_glyph_outline_w = 0;
+}
+