コード例 #1
0
ファイル: w32notify.c プロジェクト: timmartin/remacs
/* Signal to the main thread that we have file notifications for it to
   process.  */
static void
send_notifications (BYTE *info, DWORD info_size, void *desc,
		    volatile int *terminate)
{
  int done = 0;
  struct frame *f = SELECTED_FRAME ();

  /* A single buffer is used to communicate all notifications to the
     main thread.  Since both the main thread and several watcher
     threads could be active at the same time, we use a critical area
     and an "in-use" flag to synchronize them.  A watcher thread can
     only put its notifications in the buffer if it acquires the
     critical area and finds the "in-use" flag reset.  The main thread
     resets the flag after it is done processing notifications.

     FIXME: is there a better way of dealing with this?  */
  while (!done && !*terminate)
    {
      enter_crit ();
      if (!notification_buffer_in_use)
	{
	  if (info_size)
	    memcpy (file_notifications, info,
		    min (info_size, sizeof (file_notifications)));
	  notifications_size = min (info_size, sizeof (file_notifications));
	  notifications_desc = desc;
	  /* 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 ((FRAME_TERMCAP_P (f)
	       /* We send the message to the main (a.k.a. "Lisp")
		  thread, where it will wake up MsgWaitForMultipleObjects
		  inside sys_select, causing it to report that there's
		  some keyboard input available.  This will in turn cause
		  w32_console_read_socket to be called, which will pick
		  up the file notifications.  */
	       && PostThreadMessage (dwMainThreadId, WM_EMACS_FILENOTIFY, 0, 0))
	      || (FRAME_W32_P (f)
		  && PostMessage (FRAME_W32_WINDOW (f),
				  WM_EMACS_FILENOTIFY, 0, 0))
	      /* When we are running in batch mode, there's no one to
		 send a message, so we just signal the data is
		 available and hope sys_select will be called soon and
		 will read the data.  */
	      || (FRAME_INITIAL_P (f) && noninteractive))
	    notification_buffer_in_use = 1;
	  done = 1;
	}
      leave_crit ();
      if (!done)
	Sleep (5);
    }
}
コード例 #2
0
ファイル: w32notify.c プロジェクト: Ferryworld/emacs
/* Signal to the main thread that we have file notifications for it to
   process.  */
static void
send_notifications (struct notifications_set *ns)
{
  struct frame *f = SELECTED_FRAME ();

  /* We add the current notification set to the linked list.  Use the
     critical section to make sure only one thread will access the
     linked list. */
      enter_crit ();
  ns->next = notifications_set_head;
  ns->prev = notifications_set_head->prev;
  ns->prev->next = ns;
  notifications_set_head->prev = ns;
  leave_crit();

  /* 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 (FRAME_TERMCAP_P (f))
    /* We send the message to the main (a.k.a. "Lisp") thread, where
       it will wake up MsgWaitForMultipleObjects inside sys_select,
       causing it to report that there's some keyboard input
       available.  This will in turn cause w32_console_read_socket to
       be called, which will pick up the file notifications.  */
    PostThreadMessage (dwMainThreadId, WM_EMACS_FILENOTIFY, 0, 0);
  else if (FRAME_W32_P (f))
    PostMessage (FRAME_W32_WINDOW (f),
                 WM_EMACS_FILENOTIFY, 0, 0);
  /* When we are running in batch mode, there's no one to send a
     message, so we just signal the data is available and hope
     sys_select will be called soon and will read the data.  */
#if 0
  else if (FRAME_INITIAL_P (f) && noninteractive)
    ;
#endif
}
コード例 #3
0
ファイル: w32inevt.c プロジェクト: exedre/emacs
static int
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;
  int nevents = 0;

  /* 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 nevents;
    }

  enter_crit ();
  if (notification_buffer_in_use)
    {
      DWORD info_size = notifications_size;
      Lisp_Object cs = intern ("utf-16le");
      Lisp_Object obj = w32_get_watch_object (notifications_desc);

      /* 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
	  && !NILP (obj) && CONSP (obj))
	{
	  Lisp_Object callback = XCDR (obj);

	  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, cs, 0);
	      Lisp_Object action = lispy_file_action (fni->Action);

	      inev.kind = FILE_NOTIFY_EVENT;
	      inev.code = (ptrdiff_t)XINT (XIL ((EMACS_INT)notifications_desc));
	      inev.timestamp = GetTickCount ();
	      inev.modifiers = 0;
	      inev.frame_or_window = callback;
	      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 ();
  return nevents;
}
コード例 #4
0
ファイル: w32inevt.c プロジェクト: 7696122/emacs
int
handle_file_notifications (struct input_event *hold_quit)
{
  struct notifications_set *ns = NULL;
  int nevents = 0;
  int done = 0;

  /* We cannot process notification before Emacs is fully initialized,
     since we need the UTF-16LE coding-system to be set up.  */
  if (!initialized)
    {
      return nevents;
    }

  while (!done)
    {
      ns = NULL;

      /* Find out if there is a record available in the linked list of
	 notifications sets.  If so, unlink te set from the linked list.
	 Use the critical section.  */
      enter_crit ();
      if (notifications_set_head->next != notifications_set_head)
	{
	  ns = notifications_set_head->next;
	  ns->prev->next = ns->next;
	  ns->next->prev = ns->prev;
	}
      else
	done = 1;
      leave_crit();

      if (ns)
	{
	  BYTE *p = ns->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;
	  DWORD info_size = ns->size;
	  Lisp_Object cs = Qutf_16le;
	  Lisp_Object obj = w32_get_watch_object (ns->desc);

	  /* 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
	      && !NILP (obj) && CONSP (obj))
	    {
	      Lisp_Object callback = XCDR (obj);

	      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, cs, 0);
		  Lisp_Object action = lispy_file_action (fni->Action);

		  inev.kind = FILE_NOTIFY_EVENT;
		  inev.timestamp = GetTickCount ();
		  inev.modifiers = 0;
		  inev.frame_or_window = callback;
		  inev.arg = Fcons (action, fname);
		  inev.arg = list3 (make_pointer_integer (ns->desc),
				    action, fname);
		  kbd_buffer_store_event_hold (&inev, hold_quit);
		  nevents++;
		  if (!fni->NextEntryOffset)
		    break;
		  p += fni->NextEntryOffset;
		  fni = (PFILE_NOTIFY_INFORMATION)p;
		  info_size -= fni->NextEntryOffset;
		}
	    }
	  /* Free this notification set.  */
	  free (ns->notifications);
	  free (ns);
	}
    }
  return nevents;
}