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:
commit
38179f85f8
7 changed files with 205 additions and 69 deletions
|
@ -3133,7 +3133,7 @@ if test "${HAVE_W32}" = "yes"; then
|
||||||
NATIVE_IMAGE_API="yes (w32)"
|
NATIVE_IMAGE_API="yes (w32)"
|
||||||
W32_OBJ="$W32_OBJ w32image.o"
|
W32_OBJ="$W32_OBJ w32image.o"
|
||||||
fi
|
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_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32"
|
||||||
W32_RES_LINK="\$(EMACSRES)"
|
W32_RES_LINK="\$(EMACSRES)"
|
||||||
CLIENTRES="emacsclient.res"
|
CLIENTRES="emacsclient.res"
|
||||||
|
|
|
@ -1406,6 +1406,10 @@ main (int argc, char **argv)
|
||||||
the additional call here is harmless.) */
|
the additional call here is harmless.) */
|
||||||
cache_system_info ();
|
cache_system_info ();
|
||||||
#ifdef WINDOWSNT
|
#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,
|
/* 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
|
to have non-stub implementations of APIs we need to convert file
|
||||||
names between UTF-8 and the system's ANSI codepage. */
|
names between UTF-8 and the system's ANSI codepage. */
|
||||||
|
@ -1517,11 +1521,10 @@ main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
emacs_wd = emacs_get_current_dir_name ();
|
emacs_wd = emacs_get_current_dir_name ();
|
||||||
#ifdef WINDOWSNT
|
#ifdef WINDOWSNT
|
||||||
initial_wd = emacs_wd;
|
initial_wd = emacs_wd;
|
||||||
#endif
|
#endif /* WINDOWSNT */
|
||||||
#ifdef HAVE_PDUMPER
|
#ifdef HAVE_PDUMPER
|
||||||
if (dumped_with_pdumper_p ())
|
if (dumped_with_pdumper_p ())
|
||||||
pdumper_record_wd (emacs_wd);
|
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 ();
|
init_atimer ();
|
||||||
|
|
||||||
#ifdef WINDOWSNT
|
#ifdef WINDOWSNT
|
||||||
globals_of_w32 ();
|
|
||||||
#ifdef HAVE_W32NOTIFY
|
#ifdef HAVE_W32NOTIFY
|
||||||
globals_of_w32notify ();
|
globals_of_w32notify ();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10624,6 +10624,7 @@ maybe_load_unicows_dll (void)
|
||||||
pWideCharToMultiByte = (WideCharToMultiByte_Proc)
|
pWideCharToMultiByte = (WideCharToMultiByte_Proc)
|
||||||
get_proc_addr (ret, "WideCharToMultiByte");
|
get_proc_addr (ret, "WideCharToMultiByte");
|
||||||
multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
|
multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
|
||||||
|
load_unicows_dll_for_w32fns (ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -10658,6 +10659,7 @@ maybe_load_unicows_dll (void)
|
||||||
multiByteToWideCharFlags = 0;
|
multiByteToWideCharFlags = 0;
|
||||||
else
|
else
|
||||||
multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
|
multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
|
||||||
|
load_unicows_dll_for_w32fns (NULL);
|
||||||
return LoadLibrary ("Gdi32.dll");
|
return LoadLibrary ("Gdi32.dll");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,7 @@ extern void release_listen_threads (void);
|
||||||
extern void init_ntproc (int);
|
extern void init_ntproc (int);
|
||||||
extern void term_ntproc (int);
|
extern void term_ntproc (int);
|
||||||
extern HANDLE maybe_load_unicows_dll (void);
|
extern HANDLE maybe_load_unicows_dll (void);
|
||||||
|
extern void load_unicows_dll_for_w32fns (HMODULE);
|
||||||
extern void globals_of_w32 (void);
|
extern void globals_of_w32 (void);
|
||||||
|
|
||||||
extern void term_timers (void);
|
extern void term_timers (void);
|
||||||
|
|
75
src/w32fns.c
75
src/w32fns.c
|
@ -2612,6 +2612,7 @@ my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WINDOWSNT
|
#ifdef WINDOWSNT
|
||||||
|
|
||||||
/* The Windows keyboard hook callback. */
|
/* The Windows keyboard hook callback. */
|
||||||
static LRESULT CALLBACK
|
static LRESULT CALLBACK
|
||||||
funhook (int code, WPARAM w, LPARAM l)
|
funhook (int code, WPARAM w, LPARAM l)
|
||||||
|
@ -2688,8 +2689,8 @@ funhook (int code, WPARAM w, LPARAM l)
|
||||||
can prevent this by setting the
|
can prevent this by setting the
|
||||||
w32-pass-[lr]window-to-system variable to
|
w32-pass-[lr]window-to-system variable to
|
||||||
NIL. */
|
NIL. */
|
||||||
if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) ||
|
if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system))
|
||||||
(hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)))
|
|| (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)))
|
||||||
{
|
{
|
||||||
/* Not prevented - Simulate the keypress to the system. */
|
/* Not prevented - Simulate the keypress to the system. */
|
||||||
memset (inputs, 0, sizeof (inputs));
|
memset (inputs, 0, sizeof (inputs));
|
||||||
|
@ -2704,7 +2705,6 @@ funhook (int code, WPARAM w, LPARAM l)
|
||||||
inputs[1].ki.dwFlags
|
inputs[1].ki.dwFlags
|
||||||
= KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
|
= KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
|
||||||
inputs[1].ki.time = 0;
|
inputs[1].ki.time = 0;
|
||||||
SendInput (2, inputs, sizeof (INPUT));
|
|
||||||
}
|
}
|
||||||
else if (focus != NULL)
|
else if (focus != NULL)
|
||||||
{
|
{
|
||||||
|
@ -6150,6 +6150,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
|
||||||
if (harfbuzz_available)
|
if (harfbuzz_available)
|
||||||
register_font_driver (&harfbuzz_font_driver, f);
|
register_font_driver (&harfbuzz_font_driver, f);
|
||||||
#endif
|
#endif
|
||||||
|
if (uniscribe_available)
|
||||||
register_font_driver (&uniscribe_font_driver, f);
|
register_font_driver (&uniscribe_font_driver, f);
|
||||||
register_font_driver (&w32font_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)
|
if (harfbuzz_available)
|
||||||
register_font_driver (&harfbuzz_font_driver, f);
|
register_font_driver (&harfbuzz_font_driver, f);
|
||||||
#endif
|
#endif
|
||||||
|
if (uniscribe_available)
|
||||||
register_font_driver (&uniscribe_font_driver, f);
|
register_font_driver (&uniscribe_font_driver, f);
|
||||||
register_font_driver (&w32font_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
|
#ifdef WINDOWSNT
|
||||||
|
static int (WINAPI *pfnSHFileOperationW) (LPSHFILEOPSTRUCTW);
|
||||||
|
|
||||||
/* Moving files to the system recycle bin.
|
/* Moving files to the system recycle bin.
|
||||||
Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
|
Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
|
||||||
DEFUN ("system-move-file-to-trash", Fsystem_move_file_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 encoded_file;
|
||||||
Lisp_Object operation;
|
Lisp_Object operation;
|
||||||
|
|
||||||
|
/* Required on Windows 9X. */
|
||||||
|
maybe_load_unicows_dll ();
|
||||||
|
|
||||||
operation = Qdelete_file;
|
operation = Qdelete_file;
|
||||||
if (!NILP (Ffile_directory_p (filename))
|
if (!NILP (Ffile_directory_p (filename))
|
||||||
&& NILP (Ffile_symlink_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;
|
| FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
|
||||||
file_op_w.fAnyOperationsAborted = FALSE;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -8389,6 +8399,10 @@ If optional parameter FRAME is not specified, use selected frame. */)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CYGWIN
|
||||||
|
static BOOL (WINAPI *pfnShellExecuteExW) (LPSHELLEXECUTEINFOW);
|
||||||
|
#endif /* !CYGWIN */
|
||||||
|
|
||||||
DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
|
DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
|
||||||
doc: /* Get Windows to perform OPERATION on DOCUMENT.
|
doc: /* Get Windows to perform OPERATION on DOCUMENT.
|
||||||
This is a wrapper around the ShellExecute system function, which
|
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;
|
const int file_url_len = sizeof (file_url_str) - 1;
|
||||||
int doclen;
|
int doclen;
|
||||||
|
|
||||||
|
/* Required on Windows 9X. */
|
||||||
|
maybe_load_unicows_dll ();
|
||||||
|
|
||||||
if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0)
|
if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0)
|
||||||
{
|
{
|
||||||
/* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
|
/* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
|
||||||
|
@ -8598,7 +8615,7 @@ a ShowWindow flag:
|
||||||
doc_w = xmalloc (doclen * sizeof (wchar_t));
|
doc_w = xmalloc (doclen * sizeof (wchar_t));
|
||||||
pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
|
pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
|
||||||
SSDATA (document), -1, doc_w, doclen);
|
SSDATA (document), -1, doc_w, doclen);
|
||||||
if (use_unicode)
|
if (use_unicode && pfnShellExecuteExW)
|
||||||
{
|
{
|
||||||
wchar_t current_dir_w[MAX_PATH];
|
wchar_t current_dir_w[MAX_PATH];
|
||||||
SHELLEXECUTEINFOW shexinfo_w;
|
SHELLEXECUTEINFOW shexinfo_w;
|
||||||
|
@ -8650,7 +8667,7 @@ a ShowWindow flag:
|
||||||
shexinfo_w.lpDirectory = current_dir_w;
|
shexinfo_w.lpDirectory = current_dir_w;
|
||||||
shexinfo_w.nShow =
|
shexinfo_w.nShow =
|
||||||
(FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT);
|
(FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT);
|
||||||
success = ShellExecuteExW (&shexinfo_w);
|
success = (*pfnShellExecuteExW) (&shexinfo_w);
|
||||||
xfree (doc_w);
|
xfree (doc_w);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -9121,6 +9138,7 @@ and width values are in pixels.
|
||||||
menu_bar.cbSize = sizeof (menu_bar);
|
menu_bar.cbSize = sizeof (menu_bar);
|
||||||
menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
|
menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
|
||||||
menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
|
menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
|
||||||
|
|
||||||
GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
|
GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
|
||||||
single_menu_bar_height = GetSystemMetrics (SM_CYMENU);
|
single_menu_bar_height = GetSystemMetrics (SM_CYMENU);
|
||||||
wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
|
wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
|
||||||
|
@ -10007,6 +10025,8 @@ Internal use only. */)
|
||||||
|
|
||||||
#if defined WINDOWSNT && !defined HAVE_DBUS
|
#if defined WINDOWSNT && !defined HAVE_DBUS
|
||||||
|
|
||||||
|
static BOOL (WINAPI *pfnShell_NotifyIconW) (DWORD, PNOTIFYICONDATAW);
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
Tray notifications
|
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
|
/* GetLastError returns meaningless results when
|
||||||
Shell_NotifyIcon fails. */
|
Shell_NotifyIcon fails. */
|
||||||
|
@ -10305,7 +10325,7 @@ delete_tray_notification (struct frame *f, int id)
|
||||||
nidw.hWnd = FRAME_W32_WINDOW (f);
|
nidw.hWnd = FRAME_W32_WINDOW (f);
|
||||||
nidw.uID = id;
|
nidw.uID = id;
|
||||||
|
|
||||||
if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw))
|
if (!(*pfnShell_NotifyIconW) (NIM_DELETE, (PNOTIFYICONDATAW)&nidw))
|
||||||
{
|
{
|
||||||
/* GetLastError returns meaningless results when
|
/* GetLastError returns meaningless results when
|
||||||
Shell_NotifyIcon fails. */
|
Shell_NotifyIcon fails. */
|
||||||
|
@ -10372,8 +10392,8 @@ The following parameters are supported:
|
||||||
characters long, and will be truncated if it's longer.
|
characters long, and will be truncated if it's longer.
|
||||||
|
|
||||||
Note that versions of Windows before W2K support only `:icon' and `:tip'.
|
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
|
You can pass the other parameters, but they will be ignored on
|
||||||
old systems.
|
those old systems.
|
||||||
|
|
||||||
There can be at most one active notification at any given time. An
|
There can be at most one active notification at any given time. An
|
||||||
active notification must be removed by calling `w32-notification-close'
|
active notification must be removed by calling `w32-notification-close'
|
||||||
|
@ -10389,7 +10409,10 @@ usage: (w32-notification-notify &rest PARAMS) */)
|
||||||
enum NI_Severity severity;
|
enum NI_Severity severity;
|
||||||
unsigned timeout = 0;
|
unsigned timeout = 0;
|
||||||
|
|
||||||
if (nargs == 0)
|
/* Required on Windows 9X. */
|
||||||
|
maybe_load_unicows_dll ();
|
||||||
|
|
||||||
|
if (nargs == 0 || !pfnShell_NotifyIconW)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
|
|
||||||
arg_plist = Flist (nargs, args);
|
arg_plist = Flist (nargs, args);
|
||||||
|
@ -10448,7 +10471,7 @@ DEFUN ("w32-notification-close",
|
||||||
{
|
{
|
||||||
struct frame *f = SELECTED_FRAME ();
|
struct frame *f = SELECTED_FRAME ();
|
||||||
|
|
||||||
if (FIXNUMP (id))
|
if (FIXNUMP (id) && !pfnShell_NotifyIconW)
|
||||||
delete_tray_notification (f, XFIXNUM (id));
|
delete_tray_notification (f, XFIXNUM (id));
|
||||||
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
|
@ -11499,7 +11522,7 @@ globals_of_w32fns (void)
|
||||||
get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification");
|
get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification");
|
||||||
WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc)
|
WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc)
|
||||||
get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification");
|
get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification");
|
||||||
#endif
|
#endif /* WINDOWSNT */
|
||||||
|
|
||||||
/* Support OS dark mode on Windows 10 version 1809 and higher.
|
/* Support OS dark mode on Windows 10 version 1809 and higher.
|
||||||
See `w32_applytheme' which uses appropriate APIs per version of Windows.
|
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 ();
|
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
|
#ifdef NTGUI_UNICODE
|
||||||
|
|
||||||
Lisp_Object
|
Lisp_Object
|
||||||
|
|
|
@ -120,6 +120,10 @@ struct notification {
|
||||||
/* Used for communicating notifications to the main thread. */
|
/* Used for communicating notifications to the main thread. */
|
||||||
struct notifications_set *notifications_set_head;
|
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;
|
static Lisp_Object watch_list;
|
||||||
|
|
||||||
/* Signal to the main thread that we have file notifications for it to
|
/* 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
|
/* Calling ReadDirectoryChangesW quickly to watch again for new
|
||||||
notifications. */
|
notifications. */
|
||||||
if (!ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf,
|
if (!(*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf,
|
||||||
DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
|
DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
|
||||||
dirwatch->filter, &_bytes, dirwatch->io_info,
|
dirwatch->filter, &_bytes,
|
||||||
watch_completion))
|
dirwatch->io_info, watch_completion))
|
||||||
{
|
{
|
||||||
DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ()));
|
DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ()));
|
||||||
/* If this call fails, it means that the directory is not
|
/* If this call fails, it means that the directory is not
|
||||||
|
@ -284,7 +288,7 @@ watch_worker (LPVOID arg)
|
||||||
|
|
||||||
if (dirwatch->dir)
|
if (dirwatch->dir)
|
||||||
{
|
{
|
||||||
bErr = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf,
|
bErr = (*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf,
|
||||||
DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
|
DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
|
||||||
dirwatch->filter, &_bytes,
|
dirwatch->filter, &_bytes,
|
||||||
dirwatch->io_info, watch_completion);
|
dirwatch->io_info, watch_completion);
|
||||||
|
@ -575,6 +579,8 @@ generate notifications correctly, though. */)
|
||||||
report_file_notify_error ("Watching filesystem events is not supported",
|
report_file_notify_error ("Watching filesystem events is not supported",
|
||||||
Qnil);
|
Qnil);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
eassert (pfnReadDirectoryChangesW);
|
||||||
|
|
||||||
/* filenotify.el always passes us a directory, either the parent
|
/* filenotify.el always passes us a directory, either the parent
|
||||||
directory of a file to be watched, or the directory to be
|
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
|
void
|
||||||
globals_of_w32notify (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;
|
watch_list = Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,31 @@ memq_no_quit (Lisp_Object elt, Lisp_Object list)
|
||||||
return (CONSP (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. */
|
/* Font backend interface implementation. */
|
||||||
static Lisp_Object
|
static Lisp_Object
|
||||||
|
@ -202,7 +227,7 @@ uniscribe_close (struct font *font)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (uniscribe_font->cache)
|
if (uniscribe_font->cache)
|
||||||
ScriptFreeCache ((SCRIPT_CACHE) &(uniscribe_font->cache));
|
(*pfnScriptFreeCache) ((SCRIPT_CACHE) &(uniscribe_font->cache));
|
||||||
|
|
||||||
uniscribe_font->cache = NULL;
|
uniscribe_font->cache = NULL;
|
||||||
|
|
||||||
|
@ -320,7 +345,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||||
max_items = 2;
|
max_items = 2;
|
||||||
items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
|
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)
|
items, &nitems)) == E_OUTOFMEMORY)
|
||||||
{
|
{
|
||||||
/* If that wasn't enough, keep trying with one more run. */
|
/* 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;
|
int nglyphs, nchars_in_run;
|
||||||
nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
|
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
|
they are in the input LGSTRING, which is in the logical
|
||||||
order. */
|
order. */
|
||||||
items[i].a.fLogicalOrder = 1;
|
items[i].a.fLogicalOrder = 1;
|
||||||
|
|
||||||
/* Context may be NULL here, in which case the cache should be
|
/* Context may be NULL here, in which case the cache should be
|
||||||
used without needing to select the font. */
|
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,
|
chars + items[i].iCharPos, nchars_in_run,
|
||||||
max_glyphs - done_glyphs, &(items[i].a),
|
max_glyphs - done_glyphs, &(items[i].a),
|
||||||
glyphs, clusters, attributes, &nglyphs);
|
glyphs, clusters, attributes, &nglyphs);
|
||||||
|
@ -365,7 +391,9 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||||
context = get_frame_dc (f);
|
context = get_frame_dc (f);
|
||||||
old_font = SelectObject (context, FONT_HANDLE (font));
|
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,
|
chars + items[i].iCharPos, nchars_in_run,
|
||||||
max_glyphs - done_glyphs, &(items[i].a),
|
max_glyphs - done_glyphs, &(items[i].a),
|
||||||
glyphs, clusters, attributes, &nglyphs);
|
glyphs, clusters, attributes, &nglyphs);
|
||||||
|
@ -390,7 +418,9 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = ScriptPlace (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
|
result
|
||||||
|
= (*pfnScriptPlace) (context,
|
||||||
|
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
||||||
glyphs, nglyphs, attributes, &(items[i].a),
|
glyphs, nglyphs, attributes, &(items[i].a),
|
||||||
advances, offsets, &overall_metrics);
|
advances, offsets, &overall_metrics);
|
||||||
if (result == E_PENDING && !context)
|
if (result == E_PENDING && !context)
|
||||||
|
@ -400,7 +430,8 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||||
context = get_frame_dc (f);
|
context = get_frame_dc (f);
|
||||||
old_font = SelectObject (context, FONT_HANDLE (font));
|
old_font = SelectObject (context, FONT_HANDLE (font));
|
||||||
|
|
||||||
result = ScriptPlace (context,
|
result
|
||||||
|
= (*pfnScriptPlace) (context,
|
||||||
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
||||||
glyphs, nglyphs, attributes, &(items[i].a),
|
glyphs, nglyphs, attributes, &(items[i].a),
|
||||||
advances, offsets, &overall_metrics);
|
advances, offsets, &overall_metrics);
|
||||||
|
@ -469,7 +500,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||||
then updated for each successive glyph in the
|
then updated for each successive glyph in the
|
||||||
grapheme cluster. */
|
grapheme cluster. */
|
||||||
/* FIXME: Should we use DIRECTION here instead
|
/* FIXME: Should we use DIRECTION here instead
|
||||||
of what ScriptItemize guessed? */
|
of what (*pfnScriptItemize) guessed? */
|
||||||
if (items[i].a.fRTL)
|
if (items[i].a.fRTL)
|
||||||
{
|
{
|
||||||
int j1 = j;
|
int j1 = j;
|
||||||
|
@ -496,7 +527,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||||
LGLYPH_SET_ASCENT (lglyph, font->ascent);
|
LGLYPH_SET_ASCENT (lglyph, font->ascent);
|
||||||
LGLYPH_SET_DESCENT (lglyph, font->descent);
|
LGLYPH_SET_DESCENT (lglyph, font->descent);
|
||||||
|
|
||||||
result = ScriptGetGlyphABCWidth
|
result = (*pfnScriptGetGlyphABCWidth)
|
||||||
(context, (SCRIPT_CACHE) &(uniscribe_font->cache),
|
(context, (SCRIPT_CACHE) &(uniscribe_font->cache),
|
||||||
glyphs[j], &char_metric);
|
glyphs[j], &char_metric);
|
||||||
if (result == E_PENDING && !context)
|
if (result == E_PENDING && !context)
|
||||||
|
@ -505,7 +536,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
|
||||||
f = XFRAME (selected_frame);
|
f = XFRAME (selected_frame);
|
||||||
context = get_frame_dc (f);
|
context = get_frame_dc (f);
|
||||||
old_font = SelectObject (context, FONT_HANDLE (font));
|
old_font = SelectObject (context, FONT_HANDLE (font));
|
||||||
result = ScriptGetGlyphABCWidth
|
result = (*pfnScriptGetGlyphABCWidth)
|
||||||
(context, (SCRIPT_CACHE) &(uniscribe_font->cache),
|
(context, (SCRIPT_CACHE) &(uniscribe_font->cache),
|
||||||
glyphs[j], &char_metric);
|
glyphs[j], &char_metric);
|
||||||
}
|
}
|
||||||
|
@ -624,7 +655,8 @@ uniscribe_encode_char (struct font *font, int c)
|
||||||
convert surrogate pairs to glyph indexes correctly. */
|
convert surrogate pairs to glyph indexes correctly. */
|
||||||
{
|
{
|
||||||
items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
|
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;
|
HRESULT result;
|
||||||
/* Surrogates seem to need 2 here, even though only one glyph is
|
/* 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];
|
SCRIPT_VISATTR attrs[2];
|
||||||
int nglyphs;
|
int nglyphs;
|
||||||
|
|
||||||
/* Force ScriptShape to generate glyphs in the logical
|
/* Force (*pfnScriptShape) to generate glyphs in the logical
|
||||||
order. */
|
order. */
|
||||||
items[0].a.fLogicalOrder = 1;
|
items[0].a.fLogicalOrder = 1;
|
||||||
|
|
||||||
result = ScriptShape (context,
|
result = (*pfnScriptShape) (context,
|
||||||
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
||||||
ch, len, 2, &(items[0].a),
|
ch, len, 2, &(items[0].a),
|
||||||
glyphs, clusters, attrs, &nglyphs);
|
glyphs, clusters, attrs, &nglyphs);
|
||||||
|
@ -651,7 +683,8 @@ uniscribe_encode_char (struct font *font, int c)
|
||||||
f = XFRAME (selected_frame);
|
f = XFRAME (selected_frame);
|
||||||
context = get_frame_dc (f);
|
context = get_frame_dc (f);
|
||||||
old_font = SelectObject (context, FONT_HANDLE (font));
|
old_font = SelectObject (context, FONT_HANDLE (font));
|
||||||
result = ScriptShape (context,
|
result
|
||||||
|
= (*pfnScriptShape) (context,
|
||||||
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
||||||
ch, len, 2, &(items[0].a),
|
ch, len, 2, &(items[0].a),
|
||||||
glyphs, clusters, attrs, &nglyphs);
|
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
|
when shaped. But we still need the return from here
|
||||||
to be valid for the shaping engine to be invoked
|
to be valid for the shaping engine to be invoked
|
||||||
later. */
|
later. */
|
||||||
result = ScriptGetCMap (context,
|
result
|
||||||
|
= (*pfnScriptGetCMap) (context,
|
||||||
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
(SCRIPT_CACHE) &(uniscribe_font->cache),
|
||||||
ch, len, 0, glyphs);
|
ch, len, 0, glyphs);
|
||||||
if (SUCCEEDED (result) && glyphs[0])
|
if (SUCCEEDED (result) && glyphs[0])
|
||||||
|
@ -942,7 +976,7 @@ uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang,
|
||||||
|
|
||||||
no_support:
|
no_support:
|
||||||
if (cache)
|
if (cache)
|
||||||
ScriptFreeCache (&cache);
|
(*pfnScriptFreeCache) (&cache);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1505,11 +1539,43 @@ syms_of_w32uniscribe_for_pdumper (void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Don't register if Uniscribe is not available. */
|
/* Don't register if Uniscribe is not available. */
|
||||||
HMODULE uniscribe = GetModuleHandle ("usp10");
|
HMODULE uniscribe;
|
||||||
|
|
||||||
|
#ifdef WINDOWSNT
|
||||||
|
uniscribe = LoadLibrary ("usp10.dll");
|
||||||
if (!uniscribe)
|
if (!uniscribe)
|
||||||
return;
|
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;
|
uniscribe_available = 1;
|
||||||
|
#endif /* Cygwin */
|
||||||
|
|
||||||
register_font_driver (&uniscribe_font_driver, NULL);
|
register_font_driver (&uniscribe_font_driver, NULL);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue