diff options
| author | Eli Zaretskii | 2012-10-14 16:38:33 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2012-10-14 16:38:33 +0200 |
| commit | 37a4dabe8aaa51e15cf63e43710ee4b8f35d434b (patch) | |
| tree | f2e68e1b5822f726e9b1d12c96b732bff607fad3 /src | |
| parent | dd8c2f5adeba029790a007ec829e18442a4ade36 (diff) | |
| download | emacs-37a4dabe8aaa51e15cf63e43710ee4b8f35d434b.tar.gz emacs-37a4dabe8aaa51e15cf63e43710ee4b8f35d434b.zip | |
More than one watch is now supported.
Need to fix the issue with descriptor, now a pointer converted to Lisp integer.
Diffstat (limited to 'src')
| -rw-r--r-- | src/emacs.c | 1 | ||||
| -rw-r--r-- | src/w32inevt.c | 2 | ||||
| -rw-r--r-- | src/w32notify.c | 158 | ||||
| -rw-r--r-- | src/w32term.c | 2 | ||||
| -rw-r--r-- | src/w32term.h | 5 |
5 files changed, 93 insertions, 75 deletions
diff --git a/src/emacs.c b/src/emacs.c index c84da7411ad..6295450a405 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1279,6 +1279,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1279 | 1279 | ||
| 1280 | #ifdef WINDOWSNT | 1280 | #ifdef WINDOWSNT |
| 1281 | globals_of_w32 (); | 1281 | globals_of_w32 (); |
| 1282 | globals_of_w32notify (); | ||
| 1282 | /* Initialize environment from registry settings. */ | 1283 | /* Initialize environment from registry settings. */ |
| 1283 | init_environment (argv); | 1284 | init_environment (argv); |
| 1284 | init_ntproc (dumping); /* must precede init_editfns. */ | 1285 | init_ntproc (dumping); /* must precede init_editfns. */ |
diff --git a/src/w32inevt.c b/src/w32inevt.c index a5868be612c..878106d7070 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c | |||
| @@ -599,7 +599,7 @@ handle_file_notifications (struct input_event *hold_quit) | |||
| 599 | { | 599 | { |
| 600 | DWORD info_size = notifications_size; | 600 | DWORD info_size = notifications_size; |
| 601 | Lisp_Object cs = intern ("utf-16le"); | 601 | Lisp_Object cs = intern ("utf-16le"); |
| 602 | Lisp_Object obj = get_watch_object (make_number (notifications_desc)); | 602 | Lisp_Object obj = w32_get_watch_object (make_number (notifications_desc)); |
| 603 | 603 | ||
| 604 | /* notifications_size could be zero when the buffer of | 604 | /* notifications_size could be zero when the buffer of |
| 605 | notifications overflowed on the OS level, or when the | 605 | notifications overflowed on the OS level, or when the |
diff --git a/src/w32notify.c b/src/w32notify.c index bdfdf3472a0..244b0b872bf 100644 --- a/src/w32notify.c +++ b/src/w32notify.c | |||
| @@ -93,6 +93,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 93 | #include "frame.h" /* needed by termhooks.h */ | 93 | #include "frame.h" /* needed by termhooks.h */ |
| 94 | #include "termhooks.h" /* for FILE_NOTIFY_EVENT */ | 94 | #include "termhooks.h" /* for FILE_NOTIFY_EVENT */ |
| 95 | 95 | ||
| 96 | #define DIRWATCH_SIGNATURE 0x01233210 | ||
| 97 | |||
| 96 | struct notification { | 98 | struct notification { |
| 97 | BYTE *buf; /* buffer for ReadDirectoryChangesW */ | 99 | BYTE *buf; /* buffer for ReadDirectoryChangesW */ |
| 98 | OVERLAPPED *io_info; /* the OVERLAPPED structure for async I/O */ | 100 | OVERLAPPED *io_info; /* the OVERLAPPED structure for async I/O */ |
| @@ -102,17 +104,14 @@ struct notification { | |||
| 102 | HANDLE dir; /* handle to the watched directory */ | 104 | HANDLE dir; /* handle to the watched directory */ |
| 103 | HANDLE thr; /* handle to the thread that watches */ | 105 | HANDLE thr; /* handle to the thread that watches */ |
| 104 | int terminate; /* if non-zero, request for the thread to terminate */ | 106 | int terminate; /* if non-zero, request for the thread to terminate */ |
| 107 | unsigned signature; | ||
| 105 | }; | 108 | }; |
| 106 | 109 | ||
| 107 | /* FIXME: this needs to be changed to support more that one request at | ||
| 108 | a time. */ | ||
| 109 | static struct notification dirwatch; | ||
| 110 | |||
| 111 | /* Used for communicating notifications to the main thread. */ | 110 | /* Used for communicating notifications to the main thread. */ |
| 112 | int notification_buffer_in_use; | 111 | int notification_buffer_in_use; |
| 113 | BYTE file_notifications[16384]; | 112 | BYTE file_notifications[16384]; |
| 114 | DWORD notifications_size; | 113 | DWORD notifications_size; |
| 115 | HANDLE notifications_desc; | 114 | void *notifications_desc; |
| 116 | 115 | ||
| 117 | static Lisp_Object Qfile_name, Qdirectory_name, Qattributes, Qsize; | 116 | static Lisp_Object Qfile_name, Qdirectory_name, Qattributes, Qsize; |
| 118 | static Lisp_Object Qlast_write_time, Qlast_access_time, Qcreation_time; | 117 | static Lisp_Object Qlast_write_time, Qlast_access_time, Qcreation_time; |
| @@ -121,12 +120,11 @@ static Lisp_Object Qsecurity_desc, Qsubtree, watch_list; | |||
| 121 | /* Signal to the main thread that we have file notifications for it to | 120 | /* Signal to the main thread that we have file notifications for it to |
| 122 | process. */ | 121 | process. */ |
| 123 | static void | 122 | static void |
| 124 | send_notifications (BYTE *info, DWORD info_size, HANDLE hdir, int *terminate) | 123 | send_notifications (BYTE *info, DWORD info_size, void *desc, int *terminate) |
| 125 | { | 124 | { |
| 126 | int done = 0; | 125 | int done = 0; |
| 127 | FRAME_PTR f = SELECTED_FRAME (); | 126 | FRAME_PTR f = SELECTED_FRAME (); |
| 128 | 127 | ||
| 129 | |||
| 130 | /* A single buffer is used to communicate all notifications to the | 128 | /* A single buffer is used to communicate all notifications to the |
| 131 | main thread. Since both the main thread and several watcher | 129 | main thread. Since both the main thread and several watcher |
| 132 | threads could be active at the same time, we use a critical area | 130 | threads could be active at the same time, we use a critical area |
| @@ -144,7 +142,7 @@ send_notifications (BYTE *info, DWORD info_size, HANDLE hdir, int *terminate) | |||
| 144 | if (info_size) | 142 | if (info_size) |
| 145 | memcpy (file_notifications, info, info_size); | 143 | memcpy (file_notifications, info, info_size); |
| 146 | notifications_size = info_size; | 144 | notifications_size = info_size; |
| 147 | notifications_desc = hdir; | 145 | notifications_desc = desc; |
| 148 | /* If PostMessage fails, the message queue is full. If that | 146 | /* If PostMessage fails, the message queue is full. If that |
| 149 | happens, the last thing they will worry about is file | 147 | happens, the last thing they will worry about is file |
| 150 | notifications. So we effectively discard the | 148 | notifications. So we effectively discard the |
| @@ -214,7 +212,9 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info) | |||
| 214 | CancelIo on the directory we watch, and watch_end did so. | 212 | CancelIo on the directory we watch, and watch_end did so. |
| 215 | The directory handle is already closed. We should clean up | 213 | The directory handle is already closed. We should clean up |
| 216 | and exit, signalling to the thread worker routine not to | 214 | and exit, signalling to the thread worker routine not to |
| 217 | issue another call to ReadDirectoryChangesW. */ | 215 | issue another call to ReadDirectoryChangesW. Note that we |
| 216 | don't free the dirwatch object itself; this is done by the | ||
| 217 | main thread in remove_watch. */ | ||
| 218 | xfree (dirwatch->buf); | 218 | xfree (dirwatch->buf); |
| 219 | dirwatch->buf = NULL; | 219 | dirwatch->buf = NULL; |
| 220 | xfree (dirwatch->io_info); | 220 | xfree (dirwatch->io_info); |
| @@ -227,7 +227,7 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info) | |||
| 227 | else | 227 | else |
| 228 | { | 228 | { |
| 229 | /* Tell the main thread we have notifications for it. */ | 229 | /* Tell the main thread we have notifications for it. */ |
| 230 | send_notifications (dirwatch->buf, bytes_ret, dirwatch->dir, | 230 | send_notifications (dirwatch->buf, bytes_ret, dirwatch, |
| 231 | &dirwatch->terminate); | 231 | &dirwatch->terminate); |
| 232 | } | 232 | } |
| 233 | } | 233 | } |
| @@ -252,6 +252,12 @@ watch_worker (LPVOID arg) | |||
| 252 | if (!status) | 252 | if (!status) |
| 253 | { | 253 | { |
| 254 | DebPrint (("watch_worker, abnormal exit: %lu\n", GetLastError ())); | 254 | DebPrint (("watch_worker, abnormal exit: %lu\n", GetLastError ())); |
| 255 | /* We cannot remove the dirwatch object from watch_list, | ||
| 256 | because we are in a separate thread. So we free and | ||
| 257 | zero out all the pointers in the object, but do not | ||
| 258 | free the object itself. We also don't touch the | ||
| 259 | signature. This way, remove_watch can still identify | ||
| 260 | the object, remove it, and free its memory. */ | ||
| 255 | xfree (dirwatch->buf); | 261 | xfree (dirwatch->buf); |
| 256 | dirwatch->buf = NULL; | 262 | dirwatch->buf = NULL; |
| 257 | xfree (dirwatch->io_info); | 263 | xfree (dirwatch->io_info); |
| @@ -274,50 +280,51 @@ watch_worker (LPVOID arg) | |||
| 274 | 280 | ||
| 275 | /* Launch a thread to watch changes to FILE in a directory open on | 281 | /* Launch a thread to watch changes to FILE in a directory open on |
| 276 | handle HDIR. */ | 282 | handle HDIR. */ |
| 277 | static int | 283 | static struct notification * |
| 278 | start_watching (const char *file, HANDLE hdir, BOOL subdirs, DWORD flags) | 284 | start_watching (const char *file, HANDLE hdir, BOOL subdirs, DWORD flags) |
| 279 | { | 285 | { |
| 280 | dirwatch.buf = xmalloc (16384); | 286 | struct notification *dirwatch = xzalloc (sizeof (struct notification)); |
| 281 | dirwatch.io_info = xzalloc (sizeof(OVERLAPPED)); | 287 | HANDLE thr; |
| 288 | |||
| 289 | dirwatch->signature = DIRWATCH_SIGNATURE; | ||
| 290 | dirwatch->buf = xmalloc (16384); | ||
| 291 | dirwatch->io_info = xzalloc (sizeof(OVERLAPPED)); | ||
| 282 | /* Stash a pointer to dirwatch structure for use by the completion | 292 | /* Stash a pointer to dirwatch structure for use by the completion |
| 283 | routine. According to MSDN documentation of ReadDirectoryChangesW: | 293 | routine. According to MSDN documentation of ReadDirectoryChangesW: |
| 284 | "The hEvent member of the OVERLAPPED structure is not used by the | 294 | "The hEvent member of the OVERLAPPED structure is not used by the |
| 285 | system, so you can use it yourself." */ | 295 | system, so you can use it yourself." */ |
| 286 | dirwatch.io_info->hEvent = &dirwatch; | 296 | dirwatch->io_info->hEvent = dirwatch; |
| 287 | dirwatch.subtree = subdirs; | 297 | dirwatch->subtree = subdirs; |
| 288 | dirwatch.filter = flags; | 298 | dirwatch->filter = flags; |
| 289 | dirwatch.watchee = xstrdup (file); | 299 | dirwatch->watchee = xstrdup (file); |
| 290 | dirwatch.terminate = 0; | 300 | dirwatch->terminate = 0; |
| 291 | dirwatch.dir = hdir; | 301 | dirwatch->dir = hdir; |
| 292 | 302 | ||
| 293 | /* See w32proc.c where it calls CreateThread for the story behind | 303 | /* See w32proc.c where it calls CreateThread for the story behind |
| 294 | the 2nd and 5th argument in the call to CreateThread. */ | 304 | the 2nd and 5th argument in the call to CreateThread. */ |
| 295 | dirwatch.thr = CreateThread (NULL, 64 * 1024, watch_worker, | 305 | dirwatch->thr = CreateThread (NULL, 64 * 1024, watch_worker, (void *)dirwatch, |
| 296 | (void *)&dirwatch, 0x00010000, NULL); | 306 | 0x00010000, NULL); |
| 297 | 307 | ||
| 298 | if (!dirwatch.thr) | 308 | if (!dirwatch->thr) |
| 299 | { | 309 | { |
| 300 | dirwatch.terminate = 1; | 310 | xfree (dirwatch->buf); |
| 301 | xfree (dirwatch.buf); | 311 | xfree (dirwatch->io_info); |
| 302 | dirwatch.buf = NULL; | 312 | xfree (dirwatch->watchee); |
| 303 | xfree (dirwatch.io_info); | 313 | xfree (dirwatch); |
| 304 | dirwatch.io_info = NULL; | 314 | dirwatch = NULL; |
| 305 | xfree (dirwatch.watchee); | ||
| 306 | dirwatch.watchee = NULL; | ||
| 307 | dirwatch.dir = NULL; | ||
| 308 | return -1; | ||
| 309 | } | 315 | } |
| 310 | return 0; | 316 | return dirwatch; |
| 311 | } | 317 | } |
| 312 | 318 | ||
| 313 | /* Called from the main thread to start watching FILE in PARENT_DIR, | 319 | /* Called from the main thread to start watching FILE in PARENT_DIR, |
| 314 | subject to FLAGS. If SUBDIRS is TRUE, watch the subdirectories of | 320 | subject to FLAGS. If SUBDIRS is TRUE, watch the subdirectories of |
| 315 | PARENT_DIR as well. Value is the handle on which the directory is | 321 | PARENT_DIR as well. Value is a pointer to 'struct notification' |
| 316 | open. */ | 322 | used by the thread that watches the changes. */ |
| 317 | static HANDLE * | 323 | static struct notification * |
| 318 | add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags) | 324 | add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags) |
| 319 | { | 325 | { |
| 320 | HANDLE hdir; | 326 | HANDLE hdir; |
| 327 | struct notification *dirwatch = NULL; | ||
| 321 | 328 | ||
| 322 | if (!file || !*file) | 329 | if (!file || !*file) |
| 323 | return NULL; | 330 | return NULL; |
| @@ -334,18 +341,17 @@ add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags) | |||
| 334 | if (hdir == INVALID_HANDLE_VALUE) | 341 | if (hdir == INVALID_HANDLE_VALUE) |
| 335 | return NULL; | 342 | return NULL; |
| 336 | 343 | ||
| 337 | if (start_watching (file, hdir, subdirs, flags) == 0) | 344 | if ((dirwatch = start_watching (file, hdir, subdirs, flags)) == NULL) |
| 338 | return hdir; | 345 | CloseHandle (hdir); |
| 339 | 346 | ||
| 340 | CloseHandle (hdir); | 347 | return dirwatch; |
| 341 | return NULL; | ||
| 342 | } | 348 | } |
| 343 | 349 | ||
| 344 | /* Stop watching a directory specified by its handle HDIR. */ | 350 | /* Stop watching a directory specified by a pointer to its dirwatch object. */ |
| 345 | static int | 351 | static int |
| 346 | remove_watch (HANDLE hdir) | 352 | remove_watch (struct notification *dirwatch) |
| 347 | { | 353 | { |
| 348 | if (hdir == dirwatch.dir) | 354 | if (dirwatch && dirwatch->signature == DIRWATCH_SIGNATURE) |
| 349 | { | 355 | { |
| 350 | int i; | 356 | int i; |
| 351 | BOOL status; | 357 | BOOL status; |
| @@ -355,19 +361,19 @@ remove_watch (HANDLE hdir) | |||
| 355 | CancelIo on it. (CancelIoEx is available only since Vista.) | 361 | CancelIo on it. (CancelIoEx is available only since Vista.) |
| 356 | So we need to queue an APC for the worker thread telling it | 362 | So we need to queue an APC for the worker thread telling it |
| 357 | to terminate. */ | 363 | to terminate. */ |
| 358 | if (!QueueUserAPC (watch_end, dirwatch.thr, (ULONG_PTR)dirwatch.dir)) | 364 | if (!QueueUserAPC (watch_end, dirwatch->thr, (ULONG_PTR)dirwatch->dir)) |
| 359 | DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ())); | 365 | DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ())); |
| 360 | /* We also set the terminate flag, for when the thread is | 366 | /* We also set the terminate flag, for when the thread is |
| 361 | waiting on the critical section that never gets acquired. | 367 | waiting on the critical section that never gets acquired. |
| 362 | FIXME: is there a cleaner method? Using SleepEx there is a | 368 | FIXME: is there a cleaner method? Using SleepEx there is a |
| 363 | no-no, as that will lead to recursive APC invocations and | 369 | no-no, as that will lead to recursive APC invocations and |
| 364 | stack overflow. */ | 370 | stack overflow. */ |
| 365 | dirwatch.terminate = 1; | 371 | dirwatch->terminate = 1; |
| 366 | /* Wait for the thread to exit. FIXME: is there a better method | 372 | /* Wait for the thread to exit. FIXME: is there a better method |
| 367 | that is not overly complex? */ | 373 | that is not overly complex? */ |
| 368 | for (i = 0; i < 50; i++) | 374 | for (i = 0; i < 50; i++) |
| 369 | { | 375 | { |
| 370 | if (!((status = GetExitCodeThread (dirwatch.thr, &exit_code)) | 376 | if (!((status = GetExitCodeThread (dirwatch->thr, &exit_code)) |
| 371 | && exit_code == STILL_ACTIVE)) | 377 | && exit_code == STILL_ACTIVE)) |
| 372 | break; | 378 | break; |
| 373 | Sleep (10); | 379 | Sleep (10); |
| @@ -376,25 +382,29 @@ remove_watch (HANDLE hdir) | |||
| 376 | || exit_code == STILL_ACTIVE) | 382 | || exit_code == STILL_ACTIVE) |
| 377 | { | 383 | { |
| 378 | if (!(status == FALSE && err == ERROR_INVALID_HANDLE)) | 384 | if (!(status == FALSE && err == ERROR_INVALID_HANDLE)) |
| 379 | TerminateThread (dirwatch.thr, 0); | 385 | { |
| 386 | TerminateThread (dirwatch->thr, 0); | ||
| 387 | if (dirwatch->dir) | ||
| 388 | CloseHandle (dirwatch->dir); | ||
| 389 | } | ||
| 380 | } | 390 | } |
| 381 | 391 | ||
| 382 | /* Clean up. */ | 392 | /* Clean up. */ |
| 383 | if (dirwatch.thr) | 393 | if (dirwatch->thr) |
| 384 | { | 394 | { |
| 385 | CloseHandle (dirwatch.thr); | 395 | CloseHandle (dirwatch->thr); |
| 386 | dirwatch.thr = NULL; | 396 | dirwatch->thr = NULL; |
| 387 | } | 397 | } |
| 388 | return 0; | 398 | xfree (dirwatch->buf); |
| 389 | } | 399 | xfree (dirwatch->io_info); |
| 390 | else if (!dirwatch.dir) | 400 | xfree (dirwatch->watchee); |
| 391 | { | 401 | xfree (dirwatch); |
| 392 | DebPrint (("Directory handle already closed!\n")); | 402 | |
| 393 | return 0; | 403 | return 0; |
| 394 | } | 404 | } |
| 395 | else | 405 | else |
| 396 | { | 406 | { |
| 397 | DebPrint (("Unknown directory handle!\n")); | 407 | DebPrint (("Unknown dirwatch object!\n")); |
| 398 | return -1; | 408 | return -1; |
| 399 | } | 409 | } |
| 400 | } | 410 | } |
| @@ -474,9 +484,9 @@ FILE is the name of the file whose event is being reported. */) | |||
| 474 | Lisp_Object encoded_file, watch_object, watch_descriptor; | 484 | Lisp_Object encoded_file, watch_object, watch_descriptor; |
| 475 | char parent_dir[MAX_PATH], *basename; | 485 | char parent_dir[MAX_PATH], *basename; |
| 476 | size_t fn_len; | 486 | size_t fn_len; |
| 477 | HANDLE hdir; | ||
| 478 | DWORD flags; | 487 | DWORD flags; |
| 479 | BOOL subdirs = FALSE; | 488 | BOOL subdirs = FALSE; |
| 489 | struct notification *dirwatch = NULL; | ||
| 480 | Lisp_Object lisp_errstr; | 490 | Lisp_Object lisp_errstr; |
| 481 | char *errstr; | 491 | char *errstr; |
| 482 | 492 | ||
| @@ -491,10 +501,7 @@ FILE is the name of the file whose event is being reported. */) | |||
| 491 | Qnil); | 501 | Qnil); |
| 492 | } | 502 | } |
| 493 | 503 | ||
| 494 | if (dirwatch.dir) | 504 | /* We need a full absolute file name of FILE, and we need to remove |
| 495 | error ("File watch already active"); | ||
| 496 | |||
| 497 | /* We needa full absolute file name of FILE, and we need to remove | ||
| 498 | any trailing slashes from it, so that GetFullPathName below gets | 505 | any trailing slashes from it, so that GetFullPathName below gets |
| 499 | the basename part correctly. */ | 506 | the basename part correctly. */ |
| 500 | file = Fdirectory_file_name (Fexpand_file_name (file, Qnil)); | 507 | file = Fdirectory_file_name (Fexpand_file_name (file, Qnil)); |
| @@ -528,8 +535,8 @@ FILE is the name of the file whose event is being reported. */) | |||
| 528 | 535 | ||
| 529 | flags = filter_list_to_flags (filter); | 536 | flags = filter_list_to_flags (filter); |
| 530 | 537 | ||
| 531 | hdir = add_watch (parent_dir, basename, subdirs, flags); | 538 | dirwatch = add_watch (parent_dir, basename, subdirs, flags); |
| 532 | if (!hdir) | 539 | if (!dirwatch) |
| 533 | { | 540 | { |
| 534 | DWORD err = GetLastError (); | 541 | DWORD err = GetLastError (); |
| 535 | 542 | ||
| @@ -550,7 +557,7 @@ FILE is the name of the file whose event is being reported. */) | |||
| 550 | report_file_error ("Cannot watch file", Fcons (file, Qnil)); | 557 | report_file_error ("Cannot watch file", Fcons (file, Qnil)); |
| 551 | } | 558 | } |
| 552 | /* Store watch object in watch list. */ | 559 | /* Store watch object in watch list. */ |
| 553 | watch_descriptor = make_number (hdir); | 560 | watch_descriptor = make_number (dirwatch); |
| 554 | watch_object = Fcons (watch_descriptor, callback); | 561 | watch_object = Fcons (watch_descriptor, callback); |
| 555 | watch_list = Fcons (watch_object, watch_list); | 562 | watch_list = Fcons (watch_object, watch_list); |
| 556 | 563 | ||
| @@ -565,24 +572,33 @@ WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */) | |||
| 565 | (Lisp_Object watch_descriptor) | 572 | (Lisp_Object watch_descriptor) |
| 566 | { | 573 | { |
| 567 | Lisp_Object watch_object; | 574 | Lisp_Object watch_object; |
| 568 | HANDLE hdir = (HANDLE)XINT (watch_descriptor); | 575 | struct notification *dirwatch = |
| 576 | (struct notification *)XINT (watch_descriptor); | ||
| 569 | 577 | ||
| 570 | if (remove_watch (hdir) == -1) | 578 | /* Remove the watch object from watch list. Do this before freeing |
| 571 | report_file_error ("Could not remove watch", Fcons (watch_descriptor, | 579 | the object, do that even if we fail to free it, watch_list is |
| 572 | Qnil)); | 580 | kept free of junk. */ |
| 573 | |||
| 574 | /* Remove watch descriptor from watch list. */ | ||
| 575 | watch_object = Fassoc (watch_descriptor, watch_list); | 581 | watch_object = Fassoc (watch_descriptor, watch_list); |
| 576 | if (!NILP (watch_object)) | 582 | if (!NILP (watch_object)) |
| 577 | watch_list = Fdelete (watch_object, watch_list); | 583 | watch_list = Fdelete (watch_object, watch_list); |
| 578 | 584 | ||
| 585 | if (remove_watch (dirwatch) == -1) | ||
| 586 | report_file_error ("Invalid watch descriptor", Fcons (watch_descriptor, | ||
| 587 | Qnil)); | ||
| 588 | |||
| 579 | return Qnil; | 589 | return Qnil; |
| 580 | } | 590 | } |
| 581 | 591 | ||
| 582 | Lisp_Object | 592 | Lisp_Object |
| 583 | get_watch_object (Lisp_Object desc) | 593 | w32_get_watch_object (Lisp_Object desc) |
| 594 | { | ||
| 595 | return NILP (watch_list) ? Qnil : assoc_no_quit (desc, watch_list); | ||
| 596 | } | ||
| 597 | |||
| 598 | void | ||
| 599 | globals_of_w32notify (void) | ||
| 584 | { | 600 | { |
| 585 | return Fassoc (desc, watch_list); | 601 | watch_list = Qnil; |
| 586 | } | 602 | } |
| 587 | 603 | ||
| 588 | void | 604 | void |
diff --git a/src/w32term.c b/src/w32term.c index 6d19d9a93ce..1285b5a06f6 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -3282,7 +3282,7 @@ queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f, | |||
| 3282 | { | 3282 | { |
| 3283 | DWORD info_size = notifications_size; | 3283 | DWORD info_size = notifications_size; |
| 3284 | Lisp_Object cs = intern ("utf-16le"); | 3284 | Lisp_Object cs = intern ("utf-16le"); |
| 3285 | Lisp_Object obj = get_watch_object (make_number (notifications_desc)); | 3285 | Lisp_Object obj = w32_get_watch_object (make_number (notifications_desc)); |
| 3286 | 3286 | ||
| 3287 | /* notifications_size could be zero when the buffer of | 3287 | /* notifications_size could be zero when the buffer of |
| 3288 | notifications overflowed on the OS level, or when the | 3288 | notifications overflowed on the OS level, or when the |
diff --git a/src/w32term.h b/src/w32term.h index a3579c8ff60..91723c3758a 100644 --- a/src/w32term.h +++ b/src/w32term.h | |||
| @@ -685,8 +685,8 @@ extern void x_delete_display (struct w32_display_info *dpyinfo); | |||
| 685 | extern int notification_buffer_in_use; | 685 | extern int notification_buffer_in_use; |
| 686 | extern BYTE file_notifications[16384]; | 686 | extern BYTE file_notifications[16384]; |
| 687 | extern DWORD notifications_size; | 687 | extern DWORD notifications_size; |
| 688 | extern HANDLE notifications_desc; | 688 | extern void *notifications_desc; |
| 689 | extern Lisp_Object get_watch_object (Lisp_Object); | 689 | extern Lisp_Object w32_get_watch_object (Lisp_Object); |
| 690 | extern Lisp_Object lispy_file_action (DWORD); | 690 | extern Lisp_Object lispy_file_action (DWORD); |
| 691 | 691 | ||
| 692 | /* Keypad command key support. W32 doesn't have virtual keys defined | 692 | /* Keypad command key support. W32 doesn't have virtual keys defined |
| @@ -767,6 +767,7 @@ extern void syms_of_w32fns (void); | |||
| 767 | 767 | ||
| 768 | extern void globals_of_w32menu (void); | 768 | extern void globals_of_w32menu (void); |
| 769 | extern void globals_of_w32fns (void); | 769 | extern void globals_of_w32fns (void); |
| 770 | extern void globals_of_w32notify (void); | ||
| 770 | 771 | ||
| 771 | #ifdef CYGWIN | 772 | #ifdef CYGWIN |
| 772 | extern int w32_message_fd; | 773 | extern int w32_message_fd; |