/* This is the callback function for arriving signals from g_file_monitor. It shall create a Lisp event, and put it into Emacs input queue. */ static gboolean dir_monitor_callback (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { Lisp_Object symbol, monitor_object, watch_object; char *name = g_file_get_parse_name (file); char *oname = other_file ? g_file_get_parse_name (other_file) : NULL; /* Determine event symbol. */ switch (event_type) { case G_FILE_MONITOR_EVENT_CHANGED: symbol = Qchanged; break; case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: symbol = Qchanges_done_hint; break; case G_FILE_MONITOR_EVENT_DELETED: symbol = Qdeleted; break; case G_FILE_MONITOR_EVENT_CREATED: symbol = Qcreated; break; case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: symbol = Qattribute_changed; break; case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: symbol = Qpre_unmount; break; case G_FILE_MONITOR_EVENT_UNMOUNTED: symbol = Qunmounted; break; case G_FILE_MONITOR_EVENT_MOVED: symbol = Qmoved; break; default: goto cleanup; } /* Determine callback function. */ monitor_object = make_pointer_integer (monitor); eassert (INTEGERP (monitor_object)); watch_object = assq_no_quit (monitor_object, watch_list); if (CONSP (watch_object)) { /* Construct an event. */ struct input_event event; Lisp_Object otail = oname ? list1 (build_string (oname)) : Qnil; EVENT_INIT (event); event.kind = FILE_NOTIFY_EVENT; event.frame_or_window = Qnil; event.arg = list2 (Fcons (monitor_object, Fcons (symbol, Fcons (build_string (name), otail))), XCDR (watch_object)); /* Store it into the input event queue. */ kbd_buffer_store_event (&event); } /* Cleanup. */ cleanup: g_free (name); g_free (oname); return TRUE; }
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 = Qutf_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.timestamp = GetTickCount (); inev.modifiers = 0; inev.frame_or_window = callback; inev.arg = Fcons (action, fname); inev.arg = list3 (make_pointer_integer (notifications_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; } } notification_buffer_in_use = 0; } leave_crit (); return nevents; }
/* This is the callback function for arriving signals from g_file_monitor. It shall create a Lisp event, and put it into Emacs input queue. */ static gboolean dir_monitor_callback (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { Lisp_Object symbol, monitor_object, watch_object, flags; char *name = g_file_get_parse_name (file); char *oname = other_file ? g_file_get_parse_name (other_file) : NULL; /* Determine event symbol. */ switch (event_type) { case G_FILE_MONITOR_EVENT_CHANGED: symbol = Qchanged; break; case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: symbol = Qchanges_done_hint; break; case G_FILE_MONITOR_EVENT_DELETED: symbol = Qdeleted; break; case G_FILE_MONITOR_EVENT_CREATED: symbol = Qcreated; break; case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: symbol = Qattribute_changed; break; case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: symbol = Qpre_unmount; break; case G_FILE_MONITOR_EVENT_UNMOUNTED: symbol = Qunmounted; break; case G_FILE_MONITOR_EVENT_MOVED: symbol = Qmoved; break; default: goto cleanup; } /* Determine callback function. */ monitor_object = make_pointer_integer (monitor); eassert (INTEGERP (monitor_object)); watch_object = assq_no_quit (monitor_object, watch_list); if (CONSP (watch_object)) { struct input_event event; Lisp_Object otail = oname ? list1 (build_string (oname)) : Qnil; /* Check, whether event_type is expected. */ flags = XCAR (XCDR (XCDR (watch_object))); if ((!NILP (Fmember (Qchange, flags)) && !NILP (Fmember (symbol, list5 (Qchanged, Qchanges_done_hint, Qdeleted, Qcreated, Qmoved)))) || (!NILP (Fmember (Qattribute_change, flags)) && ((EQ (symbol, Qattribute_changed))))) { /* Construct an event. */ EVENT_INIT (event); event.kind = FILE_NOTIFY_EVENT; event.frame_or_window = Qnil; event.arg = list2 (Fcons (monitor_object, Fcons (symbol, Fcons (build_string (name), otail))), XCAR (XCDR (XCDR (XCDR (watch_object))))); /* Store it into the input event queue. */ kbd_buffer_store_event (&event); // XD_DEBUG_MESSAGE ("%s", XD_OBJECT_TO_STRING (event.arg)); } /* Cancel monitor if file or directory is deleted. */ if (!NILP (Fmember (symbol, list2 (Qdeleted, Qmoved))) && !g_file_monitor_is_cancelled (monitor)) g_file_monitor_cancel (monitor); } /* Cleanup. */ cleanup: g_free (name); g_free (oname); return TRUE; }