aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c8
-rw-r--r--src/w32.c2
-rw-r--r--src/w32.h1
-rw-r--r--src/w32fns.c79
-rw-r--r--src/w32notify.c42
-rw-r--r--src/w32uniscribe.c140
6 files changed, 204 insertions, 68 deletions
diff --git a/src/emacs.c b/src/emacs.c
index 77929817447..22b7a4f1038 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1395,6 +1395,10 @@ main (int argc, char **argv)
1395 the additional call here is harmless.) */ 1395 the additional call here is harmless.) */
1396 cache_system_info (); 1396 cache_system_info ();
1397#ifdef WINDOWSNT 1397#ifdef WINDOWSNT
1398 /* This must be called to initialize w32_unicode_filenames and
1399 is_windows_9x prior to w32_init_current_directory. */
1400 globals_of_w32 ();
1401
1398 /* On Windows 9X, we have to load UNICOWS.DLL as early as possible, 1402 /* On Windows 9X, we have to load UNICOWS.DLL as early as possible,
1399 to have non-stub implementations of APIs we need to convert file 1403 to have non-stub implementations of APIs we need to convert file
1400 names between UTF-8 and the system's ANSI codepage. */ 1404 names between UTF-8 and the system's ANSI codepage. */
@@ -1506,11 +1510,10 @@ main (int argc, char **argv)
1506 } 1510 }
1507 } 1511 }
1508#endif 1512#endif
1509
1510 emacs_wd = emacs_get_current_dir_name (); 1513 emacs_wd = emacs_get_current_dir_name ();
1511#ifdef WINDOWSNT 1514#ifdef WINDOWSNT
1512 initial_wd = emacs_wd; 1515 initial_wd = emacs_wd;
1513#endif 1516#endif /* WINDOWSNT */
1514#ifdef HAVE_PDUMPER 1517#ifdef HAVE_PDUMPER
1515 if (dumped_with_pdumper_p ()) 1518 if (dumped_with_pdumper_p ())
1516 pdumper_record_wd (emacs_wd); 1519 pdumper_record_wd (emacs_wd);
@@ -2165,7 +2168,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
2165 init_atimer (); 2168 init_atimer ();
2166 2169
2167#ifdef WINDOWSNT 2170#ifdef WINDOWSNT
2168 globals_of_w32 ();
2169#ifdef HAVE_W32NOTIFY 2171#ifdef HAVE_W32NOTIFY
2170 globals_of_w32notify (); 2172 globals_of_w32notify ();
2171#endif 2173#endif
diff --git a/src/w32.c b/src/w32.c
index 1c6a56bcbd9..4986d4c6676 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -10624,6 +10624,7 @@ maybe_load_unicows_dll (void)
10624 pWideCharToMultiByte = (WideCharToMultiByte_Proc) 10624 pWideCharToMultiByte = (WideCharToMultiByte_Proc)
10625 get_proc_addr (ret, "WideCharToMultiByte"); 10625 get_proc_addr (ret, "WideCharToMultiByte");
10626 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; 10626 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
10627 load_unicows_dll_for_w32fns (ret);
10627 return ret; 10628 return ret;
10628 } 10629 }
10629 else 10630 else
@@ -10658,6 +10659,7 @@ maybe_load_unicows_dll (void)
10658 multiByteToWideCharFlags = 0; 10659 multiByteToWideCharFlags = 0;
10659 else 10660 else
10660 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; 10661 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
10662 load_unicows_dll_for_w32fns (NULL);
10661 return LoadLibrary ("Gdi32.dll"); 10663 return LoadLibrary ("Gdi32.dll");
10662 } 10664 }
10663} 10665}
diff --git a/src/w32.h b/src/w32.h
index cf470ae9901..3dc79dabf4b 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -170,6 +170,7 @@ extern void release_listen_threads (void);
170extern void init_ntproc (int); 170extern void init_ntproc (int);
171extern void term_ntproc (int); 171extern void term_ntproc (int);
172extern HANDLE maybe_load_unicows_dll (void); 172extern HANDLE maybe_load_unicows_dll (void);
173extern void load_unicows_dll_for_w32fns (HMODULE);
173extern void globals_of_w32 (void); 174extern void globals_of_w32 (void);
174 175
175extern void term_timers (void); 176extern void term_timers (void);
diff --git a/src/w32fns.c b/src/w32fns.c
index 4c2f18abd08..6090eb34e82 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -2612,6 +2612,7 @@ my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2612} 2612}
2613 2613
2614#ifdef WINDOWSNT 2614#ifdef WINDOWSNT
2615
2615/* The Windows keyboard hook callback. */ 2616/* The Windows keyboard hook callback. */
2616static LRESULT CALLBACK 2617static LRESULT CALLBACK
2617funhook (int code, WPARAM w, LPARAM l) 2618funhook (int code, WPARAM w, LPARAM l)
@@ -2688,8 +2689,8 @@ funhook (int code, WPARAM w, LPARAM l)
2688 can prevent this by setting the 2689 can prevent this by setting the
2689 w32-pass-[lr]window-to-system variable to 2690 w32-pass-[lr]window-to-system variable to
2690 NIL. */ 2691 NIL. */
2691 if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) || 2692 if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system))
2692 (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system))) 2693 || (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)))
2693 { 2694 {
2694 /* Not prevented - Simulate the keypress to the system. */ 2695 /* Not prevented - Simulate the keypress to the system. */
2695 memset (inputs, 0, sizeof (inputs)); 2696 memset (inputs, 0, sizeof (inputs));
@@ -2704,7 +2705,6 @@ funhook (int code, WPARAM w, LPARAM l)
2704 inputs[1].ki.dwFlags 2705 inputs[1].ki.dwFlags
2705 = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP; 2706 = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
2706 inputs[1].ki.time = 0; 2707 inputs[1].ki.time = 0;
2707 SendInput (2, inputs, sizeof (INPUT));
2708 } 2708 }
2709 else if (focus != NULL) 2709 else if (focus != NULL)
2710 { 2710 {
@@ -6150,7 +6150,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
6150 if (harfbuzz_available) 6150 if (harfbuzz_available)
6151 register_font_driver (&harfbuzz_font_driver, f); 6151 register_font_driver (&harfbuzz_font_driver, f);
6152#endif 6152#endif
6153 register_font_driver (&uniscribe_font_driver, f); 6153 if (uniscribe_available)
6154 register_font_driver (&uniscribe_font_driver, f);
6154 register_font_driver (&w32font_driver, f); 6155 register_font_driver (&w32font_driver, f);
6155 6156
6156 gui_default_parameter (f, parameters, Qfont_backend, Qnil, 6157 gui_default_parameter (f, parameters, Qfont_backend, Qnil,
@@ -7227,7 +7228,8 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
7227 if (harfbuzz_available) 7228 if (harfbuzz_available)
7228 register_font_driver (&harfbuzz_font_driver, f); 7229 register_font_driver (&harfbuzz_font_driver, f);
7229#endif 7230#endif
7230 register_font_driver (&uniscribe_font_driver, f); 7231 if (uniscribe_available)
7232 register_font_driver (&uniscribe_font_driver, f);
7231 register_font_driver (&w32font_driver, f); 7233 register_font_driver (&w32font_driver, f);
7232 7234
7233 gui_default_parameter (f, parms, Qfont_backend, Qnil, 7235 gui_default_parameter (f, parms, Qfont_backend, Qnil,
@@ -8265,6 +8267,8 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
8265 8267
8266 8268
8267#ifdef WINDOWSNT 8269#ifdef WINDOWSNT
8270static int (WINAPI *pfnSHFileOperationW) (LPSHFILEOPSTRUCTW);
8271
8268/* Moving files to the system recycle bin. 8272/* Moving files to the system recycle bin.
8269 Used by `move-file-to-trash' instead of the default moving to ~/.Trash */ 8273 Used by `move-file-to-trash' instead of the default moving to ~/.Trash */
8270DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, 8274DEFUN ("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,
8276 Lisp_Object encoded_file; 8280 Lisp_Object encoded_file;
8277 Lisp_Object operation; 8281 Lisp_Object operation;
8278 8282
8283 /* Required on Windows 9X. */
8284 maybe_load_unicows_dll ();
8285
8279 operation = Qdelete_file; 8286 operation = Qdelete_file;
8280 if (!NILP (Ffile_directory_p (filename)) 8287 if (!NILP (Ffile_directory_p (filename))
8281 && NILP (Ffile_symlink_p (filename))) 8288 && NILP (Ffile_symlink_p (filename)))
@@ -8324,7 +8331,10 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
8324 | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS; 8331 | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
8325 file_op_w.fAnyOperationsAborted = FALSE; 8332 file_op_w.fAnyOperationsAborted = FALSE;
8326 8333
8327 result = SHFileOperationW (&file_op_w); 8334 /* This is stated to exist on all versions of Windows NT Emacs
8335 supports. */
8336 eassert (pfnSHFileOperationW);
8337 result = (*pfnSHFileOperationW) (&file_op_w);
8328 } 8338 }
8329 else 8339 else
8330 { 8340 {
@@ -8389,6 +8399,10 @@ If optional parameter FRAME is not specified, use selected frame. */)
8389 return Qnil; 8399 return Qnil;
8390} 8400}
8391 8401
8402#ifndef CYGWIN
8403static BOOL (WINAPI *pfnShellExecuteExW) (LPSHELLEXECUTEINFOW);
8404#endif /* !CYGWIN */
8405
8392DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0, 8406DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
8393 doc: /* Get Windows to perform OPERATION on DOCUMENT. 8407 doc: /* Get Windows to perform OPERATION on DOCUMENT.
8394This is a wrapper around the ShellExecute system function, which 8408This is a wrapper around the ShellExecute system function, which
@@ -8539,6 +8553,9 @@ a ShowWindow flag:
8539 const int file_url_len = sizeof (file_url_str) - 1; 8553 const int file_url_len = sizeof (file_url_str) - 1;
8540 int doclen; 8554 int doclen;
8541 8555
8556 /* Required on Windows 9X. */
8557 maybe_load_unicows_dll ();
8558
8542 if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0) 8559 if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0)
8543 { 8560 {
8544 /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to 8561 /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to
@@ -8598,7 +8615,7 @@ a ShowWindow flag:
8598 doc_w = xmalloc (doclen * sizeof (wchar_t)); 8615 doc_w = xmalloc (doclen * sizeof (wchar_t));
8599 pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, 8616 pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
8600 SSDATA (document), -1, doc_w, doclen); 8617 SSDATA (document), -1, doc_w, doclen);
8601 if (use_unicode) 8618 if (use_unicode && pfnShellExecuteExW)
8602 { 8619 {
8603 wchar_t current_dir_w[MAX_PATH]; 8620 wchar_t current_dir_w[MAX_PATH];
8604 SHELLEXECUTEINFOW shexinfo_w; 8621 SHELLEXECUTEINFOW shexinfo_w;
@@ -8650,7 +8667,7 @@ a ShowWindow flag:
8650 shexinfo_w.lpDirectory = current_dir_w; 8667 shexinfo_w.lpDirectory = current_dir_w;
8651 shexinfo_w.nShow = 8668 shexinfo_w.nShow =
8652 (FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT); 8669 (FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT);
8653 success = ShellExecuteExW (&shexinfo_w); 8670 success = (*pfnShellExecuteExW) (&shexinfo_w);
8654 xfree (doc_w); 8671 xfree (doc_w);
8655 } 8672 }
8656 else 8673 else
@@ -9121,6 +9138,7 @@ and width values are in pixels.
9121 menu_bar.cbSize = sizeof (menu_bar); 9138 menu_bar.cbSize = sizeof (menu_bar);
9122 menu_bar.rcBar.right = menu_bar.rcBar.left = 0; 9139 menu_bar.rcBar.right = menu_bar.rcBar.left = 0;
9123 menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0; 9140 menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0;
9141
9124 GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar); 9142 GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar);
9125 single_menu_bar_height = GetSystemMetrics (SM_CYMENU); 9143 single_menu_bar_height = GetSystemMetrics (SM_CYMENU);
9126 wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE); 9144 wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE);
@@ -10007,6 +10025,8 @@ Internal use only. */)
10007 10025
10008#if defined WINDOWSNT && !defined HAVE_DBUS 10026#if defined WINDOWSNT && !defined HAVE_DBUS
10009 10027
10028static BOOL (WINAPI *pfnShell_NotifyIconW) (DWORD, PNOTIFYICONDATAW);
10029
10010/*********************************************************************** 10030/***********************************************************************
10011 Tray notifications 10031 Tray notifications
10012 ***********************************************************************/ 10032 ***********************************************************************/
@@ -10273,7 +10293,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip,
10273 } 10293 }
10274 } 10294 }
10275 10295
10276 if (!Shell_NotifyIconW (NIM_ADD, (PNOTIFYICONDATAW)&nidw)) 10296 if (!(*pfnShell_NotifyIconW) (NIM_ADD, (PNOTIFYICONDATAW)&nidw))
10277 { 10297 {
10278 /* GetLastError returns meaningless results when 10298 /* GetLastError returns meaningless results when
10279 Shell_NotifyIcon fails. */ 10299 Shell_NotifyIcon fails. */
@@ -10305,7 +10325,7 @@ delete_tray_notification (struct frame *f, int id)
10305 nidw.hWnd = FRAME_W32_WINDOW (f); 10325 nidw.hWnd = FRAME_W32_WINDOW (f);
10306 nidw.uID = id; 10326 nidw.uID = id;
10307 10327
10308 if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw)) 10328 if (!(*pfnShell_NotifyIconW) (NIM_DELETE, (PNOTIFYICONDATAW)&nidw))
10309 { 10329 {
10310 /* GetLastError returns meaningless results when 10330 /* GetLastError returns meaningless results when
10311 Shell_NotifyIcon fails. */ 10331 Shell_NotifyIcon fails. */
@@ -10372,8 +10392,8 @@ The following parameters are supported:
10372 characters long, and will be truncated if it's longer. 10392 characters long, and will be truncated if it's longer.
10373 10393
10374Note that versions of Windows before W2K support only `:icon' and `:tip'. 10394Note that versions of Windows before W2K support only `:icon' and `:tip'.
10375You can pass the other parameters, but they will be ignored on those 10395You can pass the other parameters, but they will be ignored on
10376old systems. 10396those old systems.
10377 10397
10378There can be at most one active notification at any given time. An 10398There can be at most one active notification at any given time. An
10379active notification must be removed by calling `w32-notification-close' 10399active notification must be removed by calling `w32-notification-close'
@@ -10389,7 +10409,10 @@ usage: (w32-notification-notify &rest PARAMS) */)
10389 enum NI_Severity severity; 10409 enum NI_Severity severity;
10390 unsigned timeout = 0; 10410 unsigned timeout = 0;
10391 10411
10392 if (nargs == 0) 10412 /* Required on Windows 9X. */
10413 maybe_load_unicows_dll ();
10414
10415 if (nargs == 0 || !pfnShell_NotifyIconW)
10393 return Qnil; 10416 return Qnil;
10394 10417
10395 arg_plist = Flist (nargs, args); 10418 arg_plist = Flist (nargs, args);
@@ -10448,7 +10471,7 @@ DEFUN ("w32-notification-close",
10448{ 10471{
10449 struct frame *f = SELECTED_FRAME (); 10472 struct frame *f = SELECTED_FRAME ();
10450 10473
10451 if (FIXNUMP (id)) 10474 if (FIXNUMP (id) && !pfnShell_NotifyIconW)
10452 delete_tray_notification (f, XFIXNUM (id)); 10475 delete_tray_notification (f, XFIXNUM (id));
10453 10476
10454 return Qnil; 10477 return Qnil;
@@ -11499,7 +11522,7 @@ globals_of_w32fns (void)
11499 get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification"); 11522 get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification");
11500 WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc) 11523 WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc)
11501 get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification"); 11524 get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification");
11502#endif 11525#endif /* WINDOWSNT */
11503 11526
11504 /* Support OS dark mode on Windows 10 version 1809 and higher. 11527 /* Support OS dark mode on Windows 10 version 1809 and higher.
11505 See `w32_applytheme' which uses appropriate APIs per version of Windows. 11528 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. */);
11580 syms_of_w32uniscribe (); 11603 syms_of_w32uniscribe ();
11581} 11604}
11582 11605
11606#ifdef WINDOWSNT
11607
11608/* Initialize pointers to functions whose real implementations exist in
11609 UNICOWS.DLL on Windows 9X. UNICOWS should be a pointer to a loaded
11610 handle referencing UNICOWS.DLL, or NULL on Windows NT systems. */
11611
11612void
11613load_unicows_dll_for_w32fns (HMODULE unicows)
11614{
11615 if (!unicows)
11616 /* The functions following are defined by SHELL32.DLL onw Windows
11617 NT. */
11618 unicows = GetModuleHandle ("shell32");
11619
11620 pfnSHFileOperationW
11621 = (void *) get_proc_addr (unicows, "SHFileOperationW");
11622 pfnShellExecuteExW
11623 = (void *) get_proc_addr (unicows, "ShellExecuteExW");
11624#ifndef HAVE_DBUS
11625 pfnShell_NotifyIconW
11626 = (void *) get_proc_addr (unicows, "Shell_NotifyIconW");
11627#endif /* !HAVE_DBUS */
11628}
11629
11630#endif /* WINDOWSNT */
11631
11583#ifdef NTGUI_UNICODE 11632#ifdef NTGUI_UNICODE
11584 11633
11585Lisp_Object 11634Lisp_Object
diff --git a/src/w32notify.c b/src/w32notify.c
index c93e8796fe2..1001c85fdbe 100644
--- a/src/w32notify.c
+++ b/src/w32notify.c
@@ -120,6 +120,10 @@ struct notification {
120/* Used for communicating notifications to the main thread. */ 120/* Used for communicating notifications to the main thread. */
121struct notifications_set *notifications_set_head; 121struct notifications_set *notifications_set_head;
122 122
123/* Function pointers. */
124static BOOL (WINAPI *pfnReadDirectoryChangesW) (HANDLE, PVOID, DWORD, BOOL,
125 DWORD, PDWORD, LPOVERLAPPED,
126 LPOVERLAPPED_COMPLETION_ROUTINE);
123static Lisp_Object watch_list; 127static Lisp_Object watch_list;
124 128
125/* Signal to the main thread that we have file notifications for it to 129/* 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)
252 256
253 /* Calling ReadDirectoryChangesW quickly to watch again for new 257 /* Calling ReadDirectoryChangesW quickly to watch again for new
254 notifications. */ 258 notifications. */
255 if (!ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, 259 if (!(*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf,
256 DIRWATCH_BUFFER_SIZE, dirwatch->subtree, 260 DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
257 dirwatch->filter, &_bytes, dirwatch->io_info, 261 dirwatch->filter, &_bytes,
258 watch_completion)) 262 dirwatch->io_info, watch_completion))
259 { 263 {
260 DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ())); 264 DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ()));
261 /* If this call fails, it means that the directory is not 265 /* If this call fails, it means that the directory is not
@@ -270,7 +274,7 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info)
270 274
271 /* If we were asked to terminate the thread, then fire the event. */ 275 /* If we were asked to terminate the thread, then fire the event. */
272 if (terminate) 276 if (terminate)
273 SetEvent(dirwatch->terminate); 277 SetEvent (dirwatch->terminate);
274} 278}
275 279
276/* Worker routine for the watch thread. */ 280/* Worker routine for the watch thread. */
@@ -284,10 +288,10 @@ watch_worker (LPVOID arg)
284 288
285 if (dirwatch->dir) 289 if (dirwatch->dir)
286 { 290 {
287 bErr = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, 291 bErr = (*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf,
288 DIRWATCH_BUFFER_SIZE, dirwatch->subtree, 292 DIRWATCH_BUFFER_SIZE, dirwatch->subtree,
289 dirwatch->filter, &_bytes, 293 dirwatch->filter, &_bytes,
290 dirwatch->io_info, watch_completion); 294 dirwatch->io_info, watch_completion);
291 if (!bErr) 295 if (!bErr)
292 { 296 {
293 DebPrint (("ReadDirectoryChangesW: %lu\n", GetLastError ())); 297 DebPrint (("ReadDirectoryChangesW: %lu\n", GetLastError ()));
@@ -436,7 +440,7 @@ remove_watch (struct notification *dirwatch)
436 DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ())); 440 DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ()));
437 441
438 /* We also signal the thread that it can terminate. */ 442 /* We also signal the thread that it can terminate. */
439 SetEvent(dirwatch->terminate); 443 SetEvent (dirwatch->terminate);
440 444
441 /* Wait for the thread to exit. FIXME: is there a better method 445 /* Wait for the thread to exit. FIXME: is there a better method
442 that is not overly complex? */ 446 that is not overly complex? */
@@ -466,7 +470,7 @@ remove_watch (struct notification *dirwatch)
466 CloseHandle (dirwatch->thr); 470 CloseHandle (dirwatch->thr);
467 dirwatch->thr = NULL; 471 dirwatch->thr = NULL;
468 } 472 }
469 CloseHandle(dirwatch->terminate); 473 CloseHandle (dirwatch->terminate);
470 xfree (dirwatch->buf); 474 xfree (dirwatch->buf);
471 xfree (dirwatch->io_info); 475 xfree (dirwatch->io_info);
472 xfree (dirwatch->watchee); 476 xfree (dirwatch->watchee);
@@ -575,6 +579,8 @@ generate notifications correctly, though. */)
575 report_file_notify_error ("Watching filesystem events is not supported", 579 report_file_notify_error ("Watching filesystem events is not supported",
576 Qnil); 580 Qnil);
577 } 581 }
582 else
583 eassert (pfnReadDirectoryChangesW);
578 584
579 /* filenotify.el always passes us a directory, either the parent 585 /* filenotify.el always passes us a directory, either the parent
580 directory of a file to be watched, or the directory to be 586 directory of a file to be watched, or the directory to be
@@ -649,7 +655,7 @@ WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */)
649 if (!NILP (watch_object)) 655 if (!NILP (watch_object))
650 { 656 {
651 watch_list = Fdelete (watch_object, watch_list); 657 watch_list = Fdelete (watch_object, watch_list);
652 dirwatch = (struct notification *)xmint_pointer (watch_descriptor); 658 dirwatch = (struct notification *) xmint_pointer (watch_descriptor);
653 if (w32_valid_pointer_p (dirwatch, sizeof(struct notification))) 659 if (w32_valid_pointer_p (dirwatch, sizeof(struct notification)))
654 status = remove_watch (dirwatch); 660 status = remove_watch (dirwatch);
655 } 661 }
@@ -687,7 +693,7 @@ watch by calling `w32notify-rm-watch' also makes it invalid. */)
687 if (!NILP (watch_object)) 693 if (!NILP (watch_object))
688 { 694 {
689 struct notification *dirwatch = 695 struct notification *dirwatch =
690 (struct notification *)xmint_pointer (watch_descriptor); 696 (struct notification *) xmint_pointer (watch_descriptor);
691 if (w32_valid_pointer_p (dirwatch, sizeof(struct notification)) 697 if (w32_valid_pointer_p (dirwatch, sizeof(struct notification))
692 && dirwatch->dir != NULL) 698 && dirwatch->dir != NULL)
693 return Qt; 699 return Qt;
@@ -699,6 +705,16 @@ watch by calling `w32notify-rm-watch' also makes it invalid. */)
699void 705void
700globals_of_w32notify (void) 706globals_of_w32notify (void)
701{ 707{
708 HANDLE kernel32 = GetModuleHandle ("kernel32");
709
710 /* Initialize pointers to IO functions that provide file
711 notifications. In the event that these are absent, no harm will be
712 done, since their absence indicates that Emacs is running on
713 Windows 9X, where file notifications are unavailable at the
714 outset. */
715 pfnReadDirectoryChangesW
716 = (void *) get_proc_addr (kernel32, "ReadDirectoryChangesW");
717
702 watch_list = Qnil; 718 watch_list = Qnil;
703} 719}
704 720
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index dacd6dd766e..471bdf544d8 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -109,6 +109,31 @@ memq_no_quit (Lisp_Object elt, Lisp_Object list)
109} 109}
110 110
111 111
112/* Uniscribe function pointers. */
113static HRESULT (WINAPI * pfnScriptItemize) (const WCHAR *,
114 int,
115 int,
116 const SCRIPT_CONTROL *,
117 const SCRIPT_STATE *,
118 SCRIPT_ITEM *, int *);
119static HRESULT (WINAPI * pfnScriptShape) (HDC, SCRIPT_CACHE *,
120 const WCHAR *,
121 int, int, SCRIPT_ANALYSIS *,
122 WORD *, WORD *, SCRIPT_VISATTR *,
123 int *);
124static HRESULT (WINAPI * pfnScriptPlace) (HDC, SCRIPT_CACHE *,
125 const WORD *, int,
126 const SCRIPT_VISATTR *,
127 SCRIPT_ANALYSIS *,
128 int *, GOFFSET *, ABC *);
129static HRESULT (WINAPI * pfnScriptGetGlyphABCWidth) (HDC, SCRIPT_CACHE *,
130 WORD, ABC *);
131static HRESULT (WINAPI * pfnScriptFreeCache) (SCRIPT_CACHE *);
132static HRESULT (WINAPI * pfnScriptGetCMap) (HDC, SCRIPT_CACHE *,
133 const WCHAR *,
134 int, DWORD, WORD *);
135
136
112/* Font backend interface implementation. */ 137/* Font backend interface implementation. */
113static Lisp_Object 138static Lisp_Object
114uniscribe_list (struct frame *f, Lisp_Object font_spec) 139uniscribe_list (struct frame *f, Lisp_Object font_spec)
@@ -202,7 +227,7 @@ uniscribe_close (struct font *font)
202 else 227 else
203#endif 228#endif
204 if (uniscribe_font->cache) 229 if (uniscribe_font->cache)
205 ScriptFreeCache ((SCRIPT_CACHE) &(uniscribe_font->cache)); 230 (*pfnScriptFreeCache) ((SCRIPT_CACHE) &(uniscribe_font->cache));
206 231
207 uniscribe_font->cache = NULL; 232 uniscribe_font->cache = NULL;
208 233
@@ -320,8 +345,8 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
320 max_items = 2; 345 max_items = 2;
321 items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); 346 items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1);
322 347
323 while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL, 348 while ((result = (*pfnScriptItemize) (chars, nchars, max_items, NULL, NULL,
324 items, &nitems)) == E_OUTOFMEMORY) 349 items, &nitems)) == E_OUTOFMEMORY)
325 { 350 {
326 /* If that wasn't enough, keep trying with one more run. */ 351 /* If that wasn't enough, keep trying with one more run. */
327 max_items++; 352 max_items++;
@@ -344,17 +369,18 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
344 { 369 {
345 int nglyphs, nchars_in_run; 370 int nglyphs, nchars_in_run;
346 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos; 371 nchars_in_run = items[i+1].iCharPos - items[i].iCharPos;
347 /* Force ScriptShape to generate glyphs in the same order as 372 /* Force (*pfnScriptShape) to generate glyphs in the same order as
348 they are in the input LGSTRING, which is in the logical 373 they are in the input LGSTRING, which is in the logical
349 order. */ 374 order. */
350 items[i].a.fLogicalOrder = 1; 375 items[i].a.fLogicalOrder = 1;
351 376
352 /* Context may be NULL here, in which case the cache should be 377 /* Context may be NULL here, in which case the cache should be
353 used without needing to select the font. */ 378 used without needing to select the font. */
354 result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache), 379 result
355 chars + items[i].iCharPos, nchars_in_run, 380 = (*pfnScriptShape) (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
356 max_glyphs - done_glyphs, &(items[i].a), 381 chars + items[i].iCharPos, nchars_in_run,
357 glyphs, clusters, attributes, &nglyphs); 382 max_glyphs - done_glyphs, &(items[i].a),
383 glyphs, clusters, attributes, &nglyphs);
358 384
359 if (result == E_PENDING && !context) 385 if (result == E_PENDING && !context)
360 { 386 {
@@ -365,10 +391,12 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
365 context = get_frame_dc (f); 391 context = get_frame_dc (f);
366 old_font = SelectObject (context, FONT_HANDLE (font)); 392 old_font = SelectObject (context, FONT_HANDLE (font));
367 393
368 result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache), 394 result
369 chars + items[i].iCharPos, nchars_in_run, 395 = (*pfnScriptShape) (context,
370 max_glyphs - done_glyphs, &(items[i].a), 396 (SCRIPT_CACHE) &(uniscribe_font->cache),
371 glyphs, clusters, attributes, &nglyphs); 397 chars + items[i].iCharPos, nchars_in_run,
398 max_glyphs - done_glyphs, &(items[i].a),
399 glyphs, clusters, attributes, &nglyphs);
372 } 400 }
373 401
374 if (result == E_OUTOFMEMORY) 402 if (result == E_OUTOFMEMORY)
@@ -390,9 +418,11 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
390 } 418 }
391 else 419 else
392 { 420 {
393 result = ScriptPlace (context, (SCRIPT_CACHE) &(uniscribe_font->cache), 421 result
394 glyphs, nglyphs, attributes, &(items[i].a), 422 = (*pfnScriptPlace) (context,
395 advances, offsets, &overall_metrics); 423 (SCRIPT_CACHE) &(uniscribe_font->cache),
424 glyphs, nglyphs, attributes, &(items[i].a),
425 advances, offsets, &overall_metrics);
396 if (result == E_PENDING && !context) 426 if (result == E_PENDING && !context)
397 { 427 {
398 /* Cache not complete... */ 428 /* Cache not complete... */
@@ -400,10 +430,11 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
400 context = get_frame_dc (f); 430 context = get_frame_dc (f);
401 old_font = SelectObject (context, FONT_HANDLE (font)); 431 old_font = SelectObject (context, FONT_HANDLE (font));
402 432
403 result = ScriptPlace (context, 433 result
404 (SCRIPT_CACHE) &(uniscribe_font->cache), 434 = (*pfnScriptPlace) (context,
405 glyphs, nglyphs, attributes, &(items[i].a), 435 (SCRIPT_CACHE) &(uniscribe_font->cache),
406 advances, offsets, &overall_metrics); 436 glyphs, nglyphs, attributes, &(items[i].a),
437 advances, offsets, &overall_metrics);
407 } 438 }
408 if (SUCCEEDED (result)) 439 if (SUCCEEDED (result))
409 { 440 {
@@ -469,7 +500,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
469 then updated for each successive glyph in the 500 then updated for each successive glyph in the
470 grapheme cluster. */ 501 grapheme cluster. */
471 /* FIXME: Should we use DIRECTION here instead 502 /* FIXME: Should we use DIRECTION here instead
472 of what ScriptItemize guessed? */ 503 of what (*pfnScriptItemize) guessed? */
473 if (items[i].a.fRTL) 504 if (items[i].a.fRTL)
474 { 505 {
475 int j1 = j; 506 int j1 = j;
@@ -496,7 +527,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
496 LGLYPH_SET_ASCENT (lglyph, font->ascent); 527 LGLYPH_SET_ASCENT (lglyph, font->ascent);
497 LGLYPH_SET_DESCENT (lglyph, font->descent); 528 LGLYPH_SET_DESCENT (lglyph, font->descent);
498 529
499 result = ScriptGetGlyphABCWidth 530 result = (*pfnScriptGetGlyphABCWidth)
500 (context, (SCRIPT_CACHE) &(uniscribe_font->cache), 531 (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
501 glyphs[j], &char_metric); 532 glyphs[j], &char_metric);
502 if (result == E_PENDING && !context) 533 if (result == E_PENDING && !context)
@@ -505,7 +536,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction)
505 f = XFRAME (selected_frame); 536 f = XFRAME (selected_frame);
506 context = get_frame_dc (f); 537 context = get_frame_dc (f);
507 old_font = SelectObject (context, FONT_HANDLE (font)); 538 old_font = SelectObject (context, FONT_HANDLE (font));
508 result = ScriptGetGlyphABCWidth 539 result = (*pfnScriptGetGlyphABCWidth)
509 (context, (SCRIPT_CACHE) &(uniscribe_font->cache), 540 (context, (SCRIPT_CACHE) &(uniscribe_font->cache),
510 glyphs[j], &char_metric); 541 glyphs[j], &char_metric);
511 } 542 }
@@ -624,7 +655,8 @@ uniscribe_encode_char (struct font *font, int c)
624 convert surrogate pairs to glyph indexes correctly. */ 655 convert surrogate pairs to glyph indexes correctly. */
625 { 656 {
626 items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1); 657 items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1);
627 if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems))) 658 if (SUCCEEDED ((*pfnScriptItemize) (ch, len, 2, NULL, NULL, items,
659 &nitems)))
628 { 660 {
629 HRESULT result; 661 HRESULT result;
630 /* Surrogates seem to need 2 here, even though only one glyph is 662 /* Surrogates seem to need 2 here, even though only one glyph is
@@ -635,14 +667,14 @@ uniscribe_encode_char (struct font *font, int c)
635 SCRIPT_VISATTR attrs[2]; 667 SCRIPT_VISATTR attrs[2];
636 int nglyphs; 668 int nglyphs;
637 669
638 /* Force ScriptShape to generate glyphs in the logical 670 /* Force (*pfnScriptShape) to generate glyphs in the logical
639 order. */ 671 order. */
640 items[0].a.fLogicalOrder = 1; 672 items[0].a.fLogicalOrder = 1;
641 673
642 result = ScriptShape (context, 674 result = (*pfnScriptShape) (context,
643 (SCRIPT_CACHE) &(uniscribe_font->cache), 675 (SCRIPT_CACHE) &(uniscribe_font->cache),
644 ch, len, 2, &(items[0].a), 676 ch, len, 2, &(items[0].a),
645 glyphs, clusters, attrs, &nglyphs); 677 glyphs, clusters, attrs, &nglyphs);
646 678
647 if (result == E_PENDING) 679 if (result == E_PENDING)
648 { 680 {
@@ -651,10 +683,11 @@ uniscribe_encode_char (struct font *font, int c)
651 f = XFRAME (selected_frame); 683 f = XFRAME (selected_frame);
652 context = get_frame_dc (f); 684 context = get_frame_dc (f);
653 old_font = SelectObject (context, FONT_HANDLE (font)); 685 old_font = SelectObject (context, FONT_HANDLE (font));
654 result = ScriptShape (context, 686 result
655 (SCRIPT_CACHE) &(uniscribe_font->cache), 687 = (*pfnScriptShape) (context,
656 ch, len, 2, &(items[0].a), 688 (SCRIPT_CACHE) &(uniscribe_font->cache),
657 glyphs, clusters, attrs, &nglyphs); 689 ch, len, 2, &(items[0].a),
690 glyphs, clusters, attrs, &nglyphs);
658 } 691 }
659 692
660 if (SUCCEEDED (result) && nglyphs == 1) 693 if (SUCCEEDED (result) && nglyphs == 1)
@@ -670,9 +703,10 @@ uniscribe_encode_char (struct font *font, int c)
670 when shaped. But we still need the return from here 703 when shaped. But we still need the return from here
671 to be valid for the shaping engine to be invoked 704 to be valid for the shaping engine to be invoked
672 later. */ 705 later. */
673 result = ScriptGetCMap (context, 706 result
674 (SCRIPT_CACHE) &(uniscribe_font->cache), 707 = (*pfnScriptGetCMap) (context,
675 ch, len, 0, glyphs); 708 (SCRIPT_CACHE) &(uniscribe_font->cache),
709 ch, len, 0, glyphs);
676 if (SUCCEEDED (result) && glyphs[0]) 710 if (SUCCEEDED (result) && glyphs[0])
677 code = glyphs[0]; 711 code = glyphs[0];
678 } 712 }
@@ -942,7 +976,7 @@ uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang,
942 976
943 no_support: 977 no_support:
944 if (cache) 978 if (cache)
945 ScriptFreeCache (&cache); 979 (*pfnScriptFreeCache) (&cache);
946 return ret; 980 return ret;
947} 981}
948 982
@@ -1505,11 +1539,43 @@ syms_of_w32uniscribe_for_pdumper (void)
1505 return; 1539 return;
1506 1540
1507 /* Don't register if Uniscribe is not available. */ 1541 /* Don't register if Uniscribe is not available. */
1508 HMODULE uniscribe = GetModuleHandle ("usp10"); 1542 HMODULE uniscribe;
1543
1544#ifdef WINDOWSNT
1545 uniscribe = LoadLibrary ("usp10.dll");
1509 if (!uniscribe) 1546 if (!uniscribe)
1510 return; 1547 return;
1511 1548
1549 pfnScriptItemize = (void *) get_proc_addr (uniscribe, "ScriptItemize");
1550 pfnScriptShape = (void *) get_proc_addr (uniscribe, "ScriptShape");
1551 pfnScriptPlace = (void *) get_proc_addr (uniscribe, "ScriptPlace");
1552 pfnScriptGetGlyphABCWidth
1553 = (void *) get_proc_addr (uniscribe, "ScriptGetGlyphABCWidth");
1554 pfnScriptFreeCache
1555 = (void *) get_proc_addr (uniscribe, "ScriptFreeCache");
1556 pfnScriptGetCMap
1557 = (void *) get_proc_addr (uniscribe, "ScriptGetCMap");
1558 if (!pfnScriptItemize || !pfnScriptShape || !pfnScriptPlace
1559 || !pfnScriptGetGlyphABCWidth || !pfnScriptFreeCache
1560 || !pfnScriptGetCMap)
1561 {
1562 FreeLibrary (uniscribe);
1563 return;
1564 }
1565#else /* Cygwin */
1566 uniscribe = GetModuleHandle ("usp10.dll");
1567 if (!uniscribe)
1568 return;
1569
1570 pfnScriptItemize = &ScriptItemize;
1571 pfnScriptShape = &ScriptShape;
1572 pfnScriptPlace = &ScriptPlace;
1573 pfnScriptGetGlyphABCWidth = &ScriptGetGlyphABCWidth;
1574 pfnScriptFreeCache = &ScriptFreeCache;
1575 pfnScriptGetCMap = &ScriptGetCMap;
1576
1512 uniscribe_available = 1; 1577 uniscribe_available = 1;
1578#endif /* Cygwin */
1513 1579
1514 register_font_driver (&uniscribe_font_driver, NULL); 1580 register_font_driver (&uniscribe_font_driver, NULL);
1515 1581