]> git.eshelyaron.com Git - emacs.git/commitdiff
Support file notifications in a TTY session.
authorEli Zaretskii <eliz@gnu.org>
Wed, 10 Oct 2012 17:11:25 +0000 (19:11 +0200)
committerEli Zaretskii <eliz@gnu.org>
Wed, 10 Oct 2012 17:11:25 +0000 (19:11 +0200)
FIXME: file notifications detected only when the Emacs window has focus.

src/w32inevt.c
src/w32notify.c
src/w32term.c
src/w32term.h

index c322d3a0b44436bd8290c3f9a5b35641168ee493..9b63d0c24b6c84f48d4d2bb6d87d317f5fadbc79 100644 (file)
@@ -576,6 +576,73 @@ maybe_generate_resize_event (void)
                     0, 0, 0);
 }
 
+static void
+handle_file_notifications (struct input_event *hold_quit)
+{
+  BYTE *p = file_notifications;
+  FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
+  const DWORD min_size
+    = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
+  struct input_event inev;
+
+  /* We cannot process notification before Emacs is fully initialized,
+     since we need the UTF-16LE coding-system to be set up.  */
+  if (!initialized)
+    {
+      notification_buffer_in_use = 0;
+      return;
+    }
+
+  enter_crit ();
+  if (notification_buffer_in_use)
+    {
+      DWORD info_size = notifications_size;
+
+      /* notifications_size could be zero when the buffer of
+        notifications overflowed on the OS level, or when the
+        directory being watched was itself deleted.  Do nothing in
+        that case.  */
+      if (info_size)
+       {
+         EVENT_INIT (inev);
+
+         while (info_size >= min_size)
+           {
+             Lisp_Object utf_16_fn
+               = make_unibyte_string ((char *)fni->FileName,
+                                      fni->FileNameLength);
+             /* Note: mule-conf is preloaded, so utf-16le must
+                already be defined at this point.  */
+             Lisp_Object fname
+               = code_convert_string_norecord (utf_16_fn,
+                                               intern ("utf-16le"), 0);
+             Lisp_Object action = lispy_file_action (fni->Action);
+             Lisp_Object obj;
+
+             obj = get_watch_object (make_number (notifications_desc));
+             if (!NILP (obj) && CONSP (obj))
+               {
+                 inev.kind = FILE_NOTIFY_EVENT;
+                 inev.code = (ptrdiff_t)notifications_desc;
+                 inev.timestamp = GetTickCount ();
+                 inev.modifiers = 0;
+                 inev.frame_or_window = XCDR (obj);
+                 inev.arg = Fcons (action, fname);
+                 kbd_buffer_store_event_hold (&inev, hold_quit);
+               }
+
+             if (!fni->NextEntryOffset)
+               break;
+             p += fni->NextEntryOffset;
+             fni = (PFILE_NOTIFY_INFORMATION)p;
+             info_size -= fni->NextEntryOffset;
+           }
+       }
+      notification_buffer_in_use = 0;
+    }
+  leave_crit ();
+}
+
 int
 w32_console_read_socket (struct terminal *terminal,
                          struct input_event *hold_quit)
@@ -587,6 +654,7 @@ w32_console_read_socket (struct terminal *terminal,
 
   for (;;)
     {
+      handle_file_notifications (hold_quit);
       nev = fill_queue (0);
       if (nev <= 0)
         {
index 05c918d8ac8f866e7c3bbf031cbca3aea5c93b9f..595476356367a1bb64f5fc761ca120d013b96c72 100644 (file)
@@ -115,10 +115,6 @@ send_notifications (BYTE *info, DWORD info_size, HANDLE hdir, int *terminate)
   int done = 0;
   FRAME_PTR f = SELECTED_FRAME ();
 
-  /* Too bad, but PostMessage will not work in non-GUI sessions.
-     FIXME.  */
-  if (!FRAME_W32_P (f))
-    return;
 
   /* A single buffer is used to communicate all notifications to the
      main thread.  Since both the main thread and several watcher
@@ -138,11 +134,14 @@ send_notifications (BYTE *info, DWORD info_size, HANDLE hdir, int *terminate)
            memcpy (file_notifications, info, info_size);
          notifications_size = info_size;
          notifications_desc = hdir;
-         /* If PostMessage fails, the message queue is full.  If that
-            happens, the last thing they will worry about is file
-            notifications.  So we effectively discard the
-            notification in that case.  */
-         if (PostMessage (FRAME_W32_WINDOW (f), WM_EMACS_FILENOTIFY, 0, 0))
+         if (FRAME_TERMCAP_P (f)
+             || (FRAME_W32_P (f)
+                 /* If PostMessage fails, the message queue is full.
+                    If that happens, the last thing they will worry
+                    about is file notifications.  So we effectively
+                    discard the notification in that case.  */
+                 && PostMessage (FRAME_W32_WINDOW (f),
+                                 WM_EMACS_FILENOTIFY, 0, 0)))
            notification_buffer_in_use = 1;
          done = 1;
        }
index 806b82297f159214aaa8a1eac500b6a64101850e..e1a2fbbf82414a6876f07b1405bb886fa58d0a7f 100644 (file)
@@ -3218,7 +3218,7 @@ construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
 \f
 /* File event notifications (see w32notify.c).  */
 
-static Lisp_Object
+Lisp_Object
 lispy_file_action (DWORD action)
 {
   static char unknown_fmt[] = "unknown-action(%d)";
index 6e4f8594d67471a801699fa8cc58b7464cd94110..6540d0f4d3d24aa73011cb429c45fa15212fab13 100644 (file)
@@ -687,6 +687,7 @@ extern BYTE file_notifications[16384];
 extern DWORD notifications_size;
 extern HANDLE notifications_desc;
 extern Lisp_Object get_watch_object (Lisp_Object);
+extern Lisp_Object lispy_file_action (DWORD);
 
 /* Keypad command key support.  W32 doesn't have virtual keys defined
    for the function keys on the keypad (they are mapped to the standard