This source file includes following definitions.
- dir_monitor_callback
- DEFUN
- DEFUN
- DEFUN
- globals_of_gfilenotify
- syms_of_gfilenotify
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21 #include <gio/gio.h>
22 #include "lisp.h"
23 #include "coding.h"
24 #include "termhooks.h"
25 #include "keyboard.h"
26
27
28
29 static Lisp_Object watch_list;
30
31
32
33
34 static gboolean
35 dir_monitor_callback (GFileMonitor *monitor,
36 GFile *file,
37 GFile *other_file,
38 GFileMonitorEvent event_type,
39 gpointer user_data)
40 {
41 Lisp_Object symbol, monitor_object, watch_object, flags;
42 char *name = g_file_get_parse_name (file);
43 char *oname = other_file ? g_file_get_parse_name (other_file) : NULL;
44
45
46 switch (event_type)
47 {
48 case G_FILE_MONITOR_EVENT_CHANGED:
49 symbol = Qchanged;
50 break;
51 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
52 symbol = Qchanges_done_hint;
53 break;
54 case G_FILE_MONITOR_EVENT_DELETED:
55 symbol = Qdeleted;
56 break;
57 case G_FILE_MONITOR_EVENT_CREATED:
58 symbol = Qcreated;
59 break;
60 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
61 symbol = Qattribute_changed;
62 break;
63 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
64 symbol = Qpre_unmount;
65 break;
66 case G_FILE_MONITOR_EVENT_UNMOUNTED:
67 symbol = Qunmounted;
68 break;
69 case G_FILE_MONITOR_EVENT_MOVED:
70 symbol = Qmoved;
71 break;
72 default:
73 goto cleanup;
74 }
75
76
77 monitor_object = make_pointer_integer (monitor);
78 watch_object = assq_no_quit (monitor_object, watch_list);
79
80 if (CONSP (watch_object))
81 {
82 struct input_event event;
83 Lisp_Object otail = oname ? list1 (build_string (oname)) : Qnil;
84
85
86 flags = XCAR (XCDR (XCDR (watch_object)));
87 if ((!NILP (Fmember (Qchange, flags))
88 && !NILP (Fmember (symbol, list5 (Qchanged, Qchanges_done_hint,
89 Qdeleted, Qcreated, Qmoved))))
90 || (!NILP (Fmember (Qattribute_change, flags))
91 && EQ (symbol, Qattribute_changed)))
92 {
93
94 EVENT_INIT (event);
95 event.kind = FILE_NOTIFY_EVENT;
96 event.frame_or_window = Qnil;
97 event.arg = list2 (Fcons (monitor_object,
98 Fcons (symbol,
99 Fcons (build_string (name),
100 otail))),
101 XCAR (XCDR (XCDR (XCDR (watch_object)))));
102
103
104 kbd_buffer_store_event (&event);
105
106 }
107
108
109 if (!NILP (Fmember (symbol, list2 (Qdeleted, Qmoved)))
110 && strcmp (name, SSDATA (XCAR (XCDR (watch_object)))) == 0
111 && !g_file_monitor_is_cancelled (monitor))
112 g_file_monitor_cancel (monitor);
113 }
114
115
116 cleanup:
117 g_free (name);
118 g_free (oname);
119
120 return TRUE;
121 }
122
123 DEFUN ("gfile-add-watch", Fgfile_add_watch, Sgfile_add_watch, 3, 3, 0,
124 doc:
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 )
164 (Lisp_Object file, Lisp_Object flags, Lisp_Object callback)
165 {
166 Lisp_Object watch_object;
167 GFile *gfile;
168 GFileMonitor *monitor;
169 GFileMonitorFlags gflags = G_FILE_MONITOR_NONE;
170 GError *gerror = NULL;
171
172
173 CHECK_STRING (file);
174 file = Fdirectory_file_name (Fexpand_file_name (file, Qnil));
175 if (NILP (Ffile_exists_p (file)))
176 report_file_error ("File does not exist", file);
177
178 if (!FUNCTIONP (callback))
179 wrong_type_argument (Qinvalid_function, callback);
180
181
182 if (!NILP (Fmember (Qwatch_mounts, flags)))
183 gflags |= G_FILE_MONITOR_WATCH_MOUNTS;
184 if (!NILP (Fmember (Qsend_moved, flags)))
185 gflags |= G_FILE_MONITOR_SEND_MOVED;
186
187
188 gfile = g_file_new_for_path (SSDATA (ENCODE_FILE (file)));
189
190
191 monitor = g_file_monitor (gfile, gflags, NULL, &gerror);
192 g_object_unref (gfile);
193 if (gerror)
194 {
195 char msg[1024];
196 strcpy (msg, gerror->message);
197 g_error_free (gerror);
198 xsignal1 (Qfile_notify_error, build_string (msg));
199 }
200 if (! monitor)
201 xsignal2 (Qfile_notify_error, build_string ("Cannot watch file"), file);
202
203 Lisp_Object watch_descriptor = make_pointer_integer_unsafe (monitor);
204
205 if (! (FIXNUMP (watch_descriptor)
206 && XFIXNUMPTR (watch_descriptor) == monitor))
207 {
208 g_object_unref (monitor);
209 xsignal2 (Qfile_notify_error, build_string ("Unsupported file watcher"),
210 file);
211 }
212
213
214 g_file_monitor_set_rate_limit (monitor, 100);
215
216
217 g_signal_connect (monitor, "changed",
218 (GCallback) dir_monitor_callback, NULL);
219
220
221 watch_object = list4 (watch_descriptor, file, flags, callback);
222 watch_list = Fcons (watch_object, watch_list);
223
224 return watch_descriptor;
225 }
226
227 DEFUN ("gfile-rm-watch", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0,
228 doc:
229
230 )
231 (Lisp_Object watch_descriptor)
232 {
233 Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list);
234
235 if (! CONSP (watch_object))
236 xsignal2 (Qfile_notify_error, build_string ("Not a watch descriptor"),
237 watch_descriptor);
238
239 eassert (FIXNUMP (watch_descriptor));
240 GFileMonitor *monitor = XFIXNUMPTR (watch_descriptor);
241 if (!g_file_monitor_is_cancelled (monitor)
242 && !g_file_monitor_cancel (monitor))
243 xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"),
244 watch_descriptor);
245
246
247 watch_list = Fdelq (watch_object, watch_list);
248
249
250 g_object_unref (monitor);
251
252 return Qt;
253 }
254
255 DEFUN ("gfile-valid-p", Fgfile_valid_p, Sgfile_valid_p, 1, 1, 0,
256 doc:
257
258
259
260
261
262
263 )
264 (Lisp_Object watch_descriptor)
265 {
266 Lisp_Object watch_object = Fassoc (watch_descriptor, watch_list, Qnil);
267 if (NILP (watch_object))
268 return Qnil;
269 else
270 {
271 GFileMonitor *monitor = XFIXNUMPTR (watch_descriptor);
272 return g_file_monitor_is_cancelled (monitor) ? Qnil : Qt;
273 }
274 }
275
276 DEFUN ("gfile-monitor-name", Fgfile_monitor_name, Sgfile_monitor_name, 1, 1, 0,
277 doc:
278
279
280
281
282
283 )
284 (Lisp_Object watch_descriptor)
285 {
286 if (NILP (Fgfile_valid_p (watch_descriptor)))
287 return Qnil;
288 else
289 {
290 GFileMonitor *monitor = XFIXNUMPTR (watch_descriptor);
291 return intern (G_OBJECT_TYPE_NAME (monitor));
292 }
293 }
294
295
296 void
297 globals_of_gfilenotify (void)
298 {
299 #if ! GLIB_CHECK_VERSION (2, 36, 0)
300 g_type_init ();
301 #endif
302 watch_list = Qnil;
303 }
304
305 void
306 syms_of_gfilenotify (void)
307 {
308 defsubr (&Sgfile_add_watch);
309 defsubr (&Sgfile_rm_watch);
310 defsubr (&Sgfile_valid_p);
311 defsubr (&Sgfile_monitor_name);
312
313
314 DEFSYM (Qchange, "change");
315 DEFSYM (Qattribute_change, "attribute-change");
316 DEFSYM (Qwatch_mounts, "watch-mounts");
317 DEFSYM (Qsend_moved, "send-moved");
318
319
320 DEFSYM (Qchanged, "changed");
321 DEFSYM (Qchanges_done_hint, "changes-done-hint");
322
323 DEFSYM (Qdeleted, "deleted");
324 DEFSYM (Qcreated, "created");
325 DEFSYM (Qattribute_changed, "attribute-changed");
326
327 DEFSYM (Qpre_unmount, "pre-unmount");
328 DEFSYM (Qunmounted, "unmounted");
329 DEFSYM (Qmoved, "moved");
330
331 staticpro (&watch_list);
332
333 Fprovide (intern_c_string ("gfilenotify"), Qnil);
334 }