Merge remote-tracking branch 'savannah/scratch/windows-98' into emacs-30

* configure.ac (W32_LIBS): Don't link with -lusp10 on non-Cygwin
systems.

* src/emacs.c (main): Call globals_of_w32 before the startup
directory is initialized.

* src/w32.c (maybe_load_unicows_dll): Call
load_unicows_dll_for_w32fns.

* src/w32.h: Update prototypes.

* src/w32fns.c (Fx_create_frame, w32_create_tip_frame): Do not
register the Uniscribe font driver when unavailable.
(pfnSHFileOperationW): New function pointer.
(Fsystem_move_file_to_trash): Load UNICOWS.DLL if not yet
loaded.  Call SHFileOperationW through said function pointer.
(pfnShellExecuteExW): New function pointer.
(Fw32_shell_execute) [!CYGWIN]: Load UNICOWS.DLL if not yet
loaded.  Call ShellExecuteExW through said function pointer.
(pfnShell_NotifyIconW): New function pointer.
(add_tray_notification, delete_tray_notification): Call
Shell_NotifyIconW through said function pointer.
(Fw32_notification_notify): Load UNICOWS.DLL.
(Fw32_notification_close): Return if Shell_NotifyIconW is
unavailable, as when UNICOWS.DLL has yet to be loaded.
(load_unicows_dll_for_w32fns): New function.

* src/w32notify.c (pfnReadDirectoryChangesW): New function
pointer.
(watch_completion, remove_watch, Fw32notify_add_watch)
(Fw32notify_rm_watch, Fw32notify_valid_p): Call
ReadDirectoryChangesW through said function pointer, and assert
its presence.
(globals_of_w32notify): Load ReadDirectoryChangesW from
KERNEL32.DLL.

* src/w32uniscribe.c (pfnScriptItemize, pfnScriptShape)
(pfnScriptPlace, pfnScriptGetGlyphABCWidth, pfnScriptFreeCache)
(pfnScriptGetCMap): New function pointers.
(uniscribe_close, uniscribe_shape, uniscribe_encode_char)
(uniscribe_check_otf_1): Call Uniscribe functions through the
same.
(syms_of_w32uniscribe_for_pdumper): Load Uniscribe library and
required functions from the same, and if unavailable, return
while leaving uniscribe_available intact.  On Cygwin, simply
assign USP10.DLL functions to the said new function pointers.
This commit is contained in:
Po Lu 2024-06-30 10:08:22 +08:00
commit 38179f85f8
7 changed files with 205 additions and 69 deletions

View file

@ -3133,7 +3133,7 @@ if test "${HAVE_W32}" = "yes"; then
NATIVE_IMAGE_API="yes (w32)"
W32_OBJ="$W32_OBJ w32image.o"
fi
W32_LIBS="$W32_LIBS -lwinmm -lusp10 -lgdi32 -lcomdlg32"
W32_LIBS="$W32_LIBS -lwinmm -lgdi32 -lcomdlg32"
W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32"
W32_RES_LINK="\$(EMACSRES)"
CLIENTRES="emacsclient.res"

View file

@ -1406,6 +1406,10 @@ main (int argc, char **argv)
the additional call here is harmless.) */
cache_system_info ();
#ifdef WINDOWSNT
/* This must be called to initialize w32_unicode_filenames and
is_windows_9x prior to w32_init_current_directory. */
globals_of_w32 ();
/* On Windows 9X, we have to load UNICOWS.DLL as early as possible,
to have non-stub implementations of APIs we need to convert file
names between UTF-8 and the system's ANSI codepage. */
@ -1517,11 +1521,10 @@ main (int argc, char **argv)
}
}
#endif
emacs_wd = emacs_get_current_dir_name ();
#ifdef WINDOWSNT
initial_wd = emacs_wd;
#endif
#endif /* WINDOWSNT */
#ifdef HAVE_PDUMPER
if (dumped_with_pdumper_p ())
pdumper_record_wd (emacs_wd);
@ -2176,7 +2179,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
init_atimer ();
#ifdef WINDOWSNT
globals_of_w32 ();
#ifdef HAVE_W32NOTIFY
globals_of_w32notify ();
#endif

View file

@ -10624,6 +10624,7 @@ maybe_load_unicows_dll (void)
pWideCharToMultiByte = (WideCharToMultiByte_Proc)
get_proc_addr (ret, "WideCharToMultiByte");
multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
load_unicows_dll_for_w32fns (ret);
return ret;
}
else
@ -10658,6 +10659,7 @@ maybe_load_unicows_dll (void)
multiByteToWideCharFlags = 0;
else
multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
load_unicows_dll_for_w32fns (NULL);
return LoadLibrary ("Gdi32.dll");
}
}

View file

@ -170,6 +170,7 @@ extern void release_listen_threads (void);
extern void init_ntproc (int);
extern void term_ntproc (int);
extern HANDLE maybe_load_unicows_dll (void);
extern void load_unicows_dll_for_w32fns (HMODULE);
extern void globals_of_w32 (void);
extern void term_timers (void);

View file

@ -2612,6 +2612,7 @@ my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
}
#ifdef WINDOWSNT
/* The Windows keyboard hook callback. */
static LRESULT CALLBACK
funhook (int code, WPARAM w, LPARAM l)
@ -2688,8 +2689,8 @@ funhook (int code, WPARAM w, LPARAM l)
can prevent this by setting the
w32-pass-[lr]window-to-system variable to
NIL. */
if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) ||
(hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)))
if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system))
|| (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)))
{
/* Not prevented - Simulate the keypress to the system. */
memset (inputs, 0, sizeof (inputs));
@ -2704,7 +2705,6 @@ funhook (int code, WPARAM w, LPARAM l)
inputs[1].ki.dwFlags
= KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
inputs[1].ki.time = 0;
SendInput (2, inputs, sizeof (INPUT));
}
else if (focus != NULL)
{
@ -6150,6 +6150,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
if (harfbuzz_available)
register_font_driver (&harfbuzz_font_driver, f);
#endif
if (uniscribe_available)
register_font_driver (&uniscribe_font_driver, f);
register_font_driver (&w32font_driver, f);
@ -7227,6 +7228,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
if (harfbuzz_available)
register_font_driver (&harfbuzz_font_driver, f);
#endif
if (uniscribe_available)
register_font_driver (&uniscribe_font_driver, f);
register_font_driver (&w32font_driver, f);
@ -8265,6 +8267,8 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
#ifdef WINDOWSNT
static int (WINAPI *pfnSHFileOperationW) (LPSHFILEOPSTRUCTW);
/* Moving files to the system recycle bin.
Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
@ -8276,6 +8280,9 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
Lisp_Object encoded_file;
Lisp_Object operation;
/* Required on Windows 9X. */
maybe_load_unicows_dll ();
operation = Qdelete_file;
if (!NILP (Ffile_directory_p (filename))
&& NILP (Ffile_symlink_p (filename)))
@ -8324,7 +8331,10 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
| FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
file_op_w.fAnyOperationsAborted = FALSE;
result = SHFileOperationW (&file_op_w);
/* This is stated to exist on all versions of Windows NT Emacs
supports. */
eassert (pfnSHFileOperationW);
result = (*pfnSHFileOperationW) (&file_op_w);
}
else
{
@ -8389,6 +8399,10 @@ If optional parameter FRAME is not specified, use selected frame. */)
return Qnil;
}
#ifndef CYGWIN
static BOOL (WINAPI *pfnShellExecuteExW) (LPSHELLEXECUTEINFOW);
#endif /* !CYGWIN */
DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
doc: /* Get Windows to perform OPERATION on DOCUMENT.
This is a wrapper around the ShellExecute system function, which
@ -8539,6 +8553,9 @@ a ShowWindow flag:
const int file_url_len = sizeof (file_url_str) - 1;
int doclen;
/* Required on Windows 9X. */
maybe_load_unicows_dll ();
if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0)
{
/* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
@ -8598,7 +8615,7 @@ a ShowWindow flag:
doc_w = xmalloc (doclen * sizeof (wchar_t));
pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
SSDATA (document), -1, doc_w, doclen);
if (use_unicode)
if (use_unicode && pfnShellExecuteExW)
{
wchar_t current_dir_w[MAX_PATH];
SHELLEXECUTEINFOW shexinfo_w;
@ -8650,7 +8667,7 @@ a ShowWindow flag:
shexinfo_w.lpDirectory = current_dir_w;
shexinfo_w.nShow =
(FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT);
success = ShellExecuteExW (&shexinfo_w);
success = (*pfnShellExecuteExW) (&shexinfo_w);
xfree (doc_w);
}
else
@ -9121,6 +9138,7 @@ and width values are in pixels.
menu_bar.cbSize = sizeof (menu_bar);
menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
single_menu_bar_height = GetSystemMetrics (SM_CYMENU);
wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
@ -10007,6 +10025,8 @@ Internal use only. */)
#if defined WINDOWSNT && !defined HAVE_DBUS
static BOOL (WINAPI *pfnShell_NotifyIconW) (DWORD, PNOTIFYICONDATAW);
/***********************************************************************
Tray notifications
***********************************************************************/
@ -10273,7 +10293,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip,
}
}
if (!Shell_NotifyIconW (NIM_ADD, (PNOTIFYICONDATAW)&nidw))
if (!(*pfnShell_NotifyIconW) (NIM_ADD, (PNOTIFYICONDATAW)&nidw))
{
/* GetLastError returns meaningless results when
Shell_NotifyIcon fails. */
@ -10305,7 +10325,7 @@ delete_tray_notification (struct frame *f, int id)
nidw.hWnd = FRAME_W32_WINDOW (f);
nidw.uID = id;
if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw))
if (!(*pfnShell_NotifyIconW) (NIM_DELETE, (PNOTIFYICONDATAW)&nidw))
{
/* GetLastError returns meaningless results when
Shell_NotifyIcon fails. */
@ -10372,8 +10392,8 @@ The following parameters are supported:
characters long, and will be truncated if it's longer.
Note that versions of Windows before W2K support only `:icon' and `:tip'.
You can pass the other parameters, but they will be ignored on those
old systems.
You can pass the other parameters, but they will be ignored on
those old systems.
There can be at most one active notification at any given time. An
active notification must be removed by calling `w32-notification-close'
@ -10389,7 +10409,10 @@ usage: (w32-notification-notify &rest PARAMS) */)
enum NI_Severity severity;
unsigned timeout = 0;
if (nargs == 0)
/* Required on Windows 9X. */
maybe_load_unicows_dll ();
if (nargs == 0 || !pfnShell_NotifyIconW)
return Qnil;
arg_plist = Flist (nargs, args);
@ -10448,7 +10471,7 @@ DEFUN ("w32-notification-close",
{
struct frame *f = SELECTED_FRAME ();
if (FIXNUMP (id))
if (FIXNUMP (id) && !pfnShell_NotifyIconW)
delete_tray_notification (f, XFIXNUM (id));
return Qnil;
@ -11499,7 +11522,7 @@ globals_of_w32fns (void)
get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification");
WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc)
get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification");
#endif
#endif /* WINDOWSNT */
/* Support OS dark mode on Windows 10 version 1809 and higher.
See `w32_applytheme' which uses appropriate APIs per version of Windows.
@ -11580,6 +11603,32 @@ Changing the value takes effect only for frames created after the change. */);
syms_of_w32uniscribe ();
}
#ifdef WINDOWSNT
/* Initialize pointers to functions whose real implementations exist in
UNICOWS.DLL on Windows 9X. UNICOWS should be a pointer to a loaded
handle referencing UNICOWS.DLL, or NULL on Windows NT systems. */
void
load_unicows_dll_for_w32fns (HMODULE unicows)
{
if (!unicows)
/* The functions following are defined by SHELL32.DLL onw Windows
NT. */
unicows = GetModuleHandle ("shell32");
pfnSHFileOperationW
= (void *) get_proc_addr (unicows, "SHFileOperationW");
pfnShellExecuteExW
= (void *) get_proc_addr (unicows, "ShellExecuteExW");
#ifndef HAVE_DBUS
pfnShell_NotifyIconW
= (void *) get_proc_addr (unicows, "Shell_NotifyIconW");
#endif /* !HAVE_DBUS */
}
#endif /* WINDOWSNT */
#ifdef NTGUI_UNICODE
Lisp_Object

View file

@ -120,6 +120,10 @@ struct notification {
/* Used for communicating notifications to the main thread. */
struct notifications_set *notifications_set_head;
/* Function pointers. */
static BOOL (WINAPI *pfnReadDirectoryChangesW) (HANDLE, PVOID, DWORD, BOOL,
DWORD, PDWORD, LPOVERLAPPED,
LPOVERLAPPED_COMPLETION_ROUTINE);
static Lisp_Object watch_list;
/* Signal to the main thread that we have file notifications for it to
@ -252,10 +256,10 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info)
/* Calling ReadDirectoryChangesW quickly to watch again for new
notifications. */
if (!ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf,
if (!(*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf,
DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
dirwatch->filter, &_bytes, dirwatch->io_info,
watch_completion))
dirwatch->filter, &_bytes,
dirwatch->io_info, watch_completion))
{
DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ()));
/* If this call fails, it means that the directory is not
@ -284,7 +288,7 @@ watch_worker (LPVOID arg)
if (dirwatch->dir)
{
bErr = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf,
bErr = (*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf,
DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
dirwatch->filter, &_bytes,
dirwatch->io_info, watch_completion);
@ -575,6 +579,8 @@ generate notifications correctly, though. */)
report_file_notify_error ("Watching filesystem events is not supported",
Qnil);
}
else
eassert (pfnReadDirectoryChangesW);
/* filenotify.el always passes us a directory, either the parent
directory of a file to be watched, or the directory to be
@ -699,6 +705,16 @@ watch by calling `w32notify-rm-watch' also makes it invalid. */)
void
globals_of_w32notify (void)
{
HANDLE kernel32 = GetModuleHandle ("kernel32");
/* Initialize pointers to IO functions that provide file
notifications. In the event that these are absent, no harm will be
done, since their absence indicates that Emacs is running on
Windows 9X, where file notifications are unavailable at the
outset. */
pfnReadDirectoryChangesW
= (void *) get_proc_addr (kernel32, "ReadDirectoryChangesW");
watch_list = Qnil;
}

View file

@ -108,6 +108,31 @@ memq_no_quit (Lisp_Object elt, Lisp_Object list)
return (CONSP (list));
}
/* Uniscribe function pointers. */
static HRESULT (WINAPI * pfnScriptItemize) (const WCHAR *,
int,
int,
const SCRIPT_CONTROL *,
const SCRIPT_STATE *,
SCRIPT_ITEM *, int *);
static HRESULT (WINAPI * pfnScriptShape) (HDC, SCRIPT_CACHE *,
const WCHAR *,
int, int, SCRIPT_ANALYSIS *,
WORD *, WORD *, SCRIPT_VISATTR *,
int *);
static HRESULT (WINAPI * pfnScriptPlace) (HDC, SCRIPT_CACHE *,
const WORD *, int,
const SCRIPT_VISATTR *,
SCRIPT_ANALYSIS *,
int *, GOFFSET *, ABC *);
static HRESULT (WINAPI * pfnScriptGetGlyphABCWidth) (HDC, SCRIPT_CACHE *,
WORD, ABC *);
static HRESULT (WINAPI * pfnScriptFreeCache) (SCRIPT_CACHE *);
static HRESULT (WINAPI * pfnScriptGetCMap) (HDC, SCRIPT_CACHE *,
const WCHAR *,
int, DWORD, WORD *);
/* Font backend interface implementation. */
static Lisp_Object
@ -202,7 +227,7 @@ uniscribe_close (struct font *font)
else
#endif
if (uniscribe_font->cache)
ScriptFreeCache ((SCRIPT_CACHE) &(uniscribe_font->cache));
(*pfnScriptFreeCache) ((SCRIPT_CACHE) &(uniscribe_font->cache));
uniscribe_font->cache = NULL;
@ -320,7 +345,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
max_items = 2;
items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL,
while ((result = (*pfnScriptItemize) (chars, nchars, max_items, NULL, NULL,
items, &nitems)) == E_OUTOFMEMORY)
{
/* If that wasn't enough, keep trying with one more run. */
@ -344,14 +369,15 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
{
int nglyphs, nchars_in_run;
nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
/* Force ScriptShape to generate glyphs in the same order as
/* Force (*pfnScriptShape) to generate glyphs in the same order as
they are in the input LGSTRING, which is in the logical
order. */
items[i].a.fLogicalOrder = 1;
/* Context may be NULL here, in which case the cache should be
used without needing to select the font. */
result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
result
= (*pfnScriptShape) (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
chars + items[i].iCharPos, nchars_in_run,
max_glyphs - done_glyphs, &(items[i].a),
glyphs, clusters, attributes, &nglyphs);
@ -365,7 +391,9 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
context = get_frame_dc (f);
old_font = SelectObject (context, FONT_HANDLE (font));
result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
result
= (*pfnScriptShape) (context,
(SCRIPT_CACHE) &(uniscribe_font->cache),
chars + items[i].iCharPos, nchars_in_run,
max_glyphs - done_glyphs, &(items[i].a),
glyphs, clusters, attributes, &nglyphs);
@ -390,7 +418,9 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
}
else
{
result = ScriptPlace (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
result
= (*pfnScriptPlace) (context,
(SCRIPT_CACHE) &(uniscribe_font->cache),
glyphs, nglyphs, attributes, &(items[i].a),
advances, offsets, &overall_metrics);
if (result == E_PENDING && !context)
@ -400,7 +430,8 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
context = get_frame_dc (f);
old_font = SelectObject (context, FONT_HANDLE (font));
result = ScriptPlace (context,
result
= (*pfnScriptPlace) (context,
(SCRIPT_CACHE) &(uniscribe_font->cache),
glyphs, nglyphs, attributes, &(items[i].a),
advances, offsets, &overall_metrics);
@ -469,7 +500,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
then updated for each successive glyph in the
grapheme cluster. */
/* FIXME: Should we use DIRECTION here instead
of what ScriptItemize guessed? */
of what (*pfnScriptItemize) guessed? */
if (items[i].a.fRTL)
{
int j1 = j;
@ -496,7 +527,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
LGLYPH_SET_ASCENT (lglyph, font->ascent);
LGLYPH_SET_DESCENT (lglyph, font->descent);
result = ScriptGetGlyphABCWidth
result = (*pfnScriptGetGlyphABCWidth)
(context, (SCRIPT_CACHE) &(uniscribe_font->cache),
glyphs[j], &char_metric);
if (result == E_PENDING && !context)
@ -505,7 +536,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
f = XFRAME (selected_frame);
context = get_frame_dc (f);
old_font = SelectObject (context, FONT_HANDLE (font));
result = ScriptGetGlyphABCWidth
result = (*pfnScriptGetGlyphABCWidth)
(context, (SCRIPT_CACHE) &(uniscribe_font->cache),
glyphs[j], &char_metric);
}
@ -624,7 +655,8 @@ uniscribe_encode_char (struct font *font, int c)
convert surrogate pairs to glyph indexes correctly. */
{
items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems)))
if (SUCCEEDED ((*pfnScriptItemize) (ch, len, 2, NULL, NULL, items,
&nitems)))
{
HRESULT result;
/* Surrogates seem to need 2 here, even though only one glyph is
@ -635,11 +667,11 @@ uniscribe_encode_char (struct font *font, int c)
SCRIPT_VISATTR attrs[2];
int nglyphs;
/* Force ScriptShape to generate glyphs in the logical
/* Force (*pfnScriptShape) to generate glyphs in the logical
order. */
items[0].a.fLogicalOrder = 1;
result = ScriptShape (context,
result = (*pfnScriptShape) (context,
(SCRIPT_CACHE) &(uniscribe_font->cache),
ch, len, 2, &(items[0].a),
glyphs, clusters, attrs, &nglyphs);
@ -651,7 +683,8 @@ uniscribe_encode_char (struct font *font, int c)
f = XFRAME (selected_frame);
context = get_frame_dc (f);
old_font = SelectObject (context, FONT_HANDLE (font));
result = ScriptShape (context,
result
= (*pfnScriptShape) (context,
(SCRIPT_CACHE) &(uniscribe_font->cache),
ch, len, 2, &(items[0].a),
glyphs, clusters, attrs, &nglyphs);
@ -670,7 +703,8 @@ uniscribe_encode_char (struct font *font, int c)
when shaped. But we still need the return from here
to be valid for the shaping engine to be invoked
later. */
result = ScriptGetCMap (context,
result
= (*pfnScriptGetCMap) (context,
(SCRIPT_CACHE) &(uniscribe_font->cache),
ch, len, 0, glyphs);
if (SUCCEEDED (result) && glyphs[0])
@ -942,7 +976,7 @@ uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang,
no_support:
if (cache)
ScriptFreeCache (&cache);
(*pfnScriptFreeCache) (&cache);
return ret;
}
@ -1505,11 +1539,43 @@ syms_of_w32uniscribe_for_pdumper (void)
return;
/* Don't register if Uniscribe is not available. */
HMODULE uniscribe = GetModuleHandle ("usp10");
HMODULE uniscribe;
#ifdef WINDOWSNT
uniscribe = LoadLibrary ("usp10.dll");
if (!uniscribe)
return;
pfnScriptItemize = (void *) get_proc_addr (uniscribe, "ScriptItemize");
pfnScriptShape = (void *) get_proc_addr (uniscribe, "ScriptShape");
pfnScriptPlace = (void *) get_proc_addr (uniscribe, "ScriptPlace");
pfnScriptGetGlyphABCWidth
= (void *) get_proc_addr (uniscribe, "ScriptGetGlyphABCWidth");
pfnScriptFreeCache
= (void *) get_proc_addr (uniscribe, "ScriptFreeCache");
pfnScriptGetCMap
= (void *) get_proc_addr (uniscribe, "ScriptGetCMap");
if (!pfnScriptItemize || !pfnScriptShape || !pfnScriptPlace
|| !pfnScriptGetGlyphABCWidth || !pfnScriptFreeCache
|| !pfnScriptGetCMap)
{
FreeLibrary (uniscribe);
return;
}
#else /* Cygwin */
uniscribe = GetModuleHandle ("usp10.dll");
if (!uniscribe)
return;
pfnScriptItemize = &ScriptItemize;
pfnScriptShape = &ScriptShape;
pfnScriptPlace = &ScriptPlace;
pfnScriptGetGlyphABCWidth = &ScriptGetGlyphABCWidth;
pfnScriptFreeCache = &ScriptFreeCache;
pfnScriptGetCMap = &ScriptGetCMap;
uniscribe_available = 1;
#endif /* Cygwin */
register_font_driver (&uniscribe_font_driver, NULL);