diff options
| author | Po Lu | 2024-06-23 16:28:22 +0800 |
|---|---|---|
| committer | Po Lu | 2024-06-23 16:28:22 +0800 |
| commit | 18e7a9f3d0c27385f8efeb2b1ef80b3446dca288 (patch) | |
| tree | 65501bcc78c32cb1b0972b36ddd344d044faa83e /src/w32notify.c | |
| parent | 60070d0d749ecd711949683108305fe50bf39d1a (diff) | |
| download | emacs-18e7a9f3d0c27385f8efeb2b1ef80b3446dca288.tar.gz emacs-18e7a9f3d0c27385f8efeb2b1ef80b3446dca288.zip | |
Restore functionality on Windows 98
* 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.
Diffstat (limited to 'src/w32notify.c')
| -rw-r--r-- | src/w32notify.c | 42 |
1 files changed, 29 insertions, 13 deletions
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. */ |
| 121 | struct notifications_set *notifications_set_head; | 121 | struct notifications_set *notifications_set_head; |
| 122 | 122 | ||
| 123 | /* Function pointers. */ | ||
| 124 | static BOOL (WINAPI *pfnReadDirectoryChangesW) (HANDLE, PVOID, DWORD, BOOL, | ||
| 125 | DWORD, PDWORD, LPOVERLAPPED, | ||
| 126 | LPOVERLAPPED_COMPLETION_ROUTINE); | ||
| 123 | static Lisp_Object watch_list; | 127 | static 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. */) | |||
| 699 | void | 705 | void |
| 700 | globals_of_w32notify (void) | 706 | globals_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 | ||