/* Add a new watch to watch-descriptor WD watching FILENAME and using IMASK and CALLBACK. Return a cons (DESCRIPTOR . ID) uniquely identifying the new watch. */ static Lisp_Object add_watch (int wd, Lisp_Object filename, uint32_t imask, Lisp_Object callback) { Lisp_Object descriptor = INTEGER_TO_CONS (wd); Lisp_Object tail = assoc_no_quit (descriptor, watch_list); Lisp_Object watch, watch_id; Lisp_Object mask = INTEGER_TO_CONS (imask); EMACS_INT id = 0; if (NILP (tail)) { tail = list1 (descriptor); watch_list = Fcons (tail, watch_list); } else { /* Assign a watch ID that is not already in use, by looking for a gap in the existing sorted list. */ for (; ! NILP (XCDR (tail)); tail = XCDR (tail), id++) if (!EQ (XCAR (XCAR (XCDR (tail))), make_number (id))) break; if (MOST_POSITIVE_FIXNUM < id) emacs_abort (); } /* Insert the newly-assigned ID into the previously-discovered gap, which is possibly at the end of the list. Inserting it there keeps the list sorted. */ watch_id = make_number (id); watch = list4 (watch_id, filename, callback, mask); XSETCDR (tail, Fcons (watch, XCDR (tail))); return Fcons (descriptor, watch_id); }
static Lisp_Object inotifyevent_to_event (Lisp_Object watch, struct inotify_event const *ev) { Lisp_Object name; uint32_t mask; CONS_TO_INTEGER (Fnth (make_number (3), watch), uint32_t, mask); if (! (mask & ev->mask)) return Qnil; if (ev->len > 0) { size_t const len = strlen (ev->name); name = make_unibyte_string (ev->name, min (len, ev->len)); name = DECODE_FILE (name); } else name = XCAR (XCDR (watch)); return list2 (list4 (Fcons (INTEGER_TO_CONS (ev->wd), XCAR (watch)), mask_to_aspects (ev->mask), name, INTEGER_TO_CONS (ev->cookie)), Fnth (make_number (2), watch)); }
void record_first_change (void) { struct buffer *base_buffer = current_buffer; if (EQ (BVAR (current_buffer, undo_list), Qt)) return; if (current_buffer != last_undo_buffer) Fundo_boundary (); last_undo_buffer = current_buffer; if (base_buffer->base_buffer) base_buffer = base_buffer->base_buffer; BVAR (current_buffer, undo_list) = Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)), BVAR (current_buffer, undo_list)); }
/* This callback is called when the FD is available for read. The inotify events are read from FD and converted into input_events. */ static void inotify_callback (int fd, void *_) { int to_read; if (ioctl (fd, FIONREAD, &to_read) < 0) report_file_notify_error ("Error while retrieving file system events", Qnil); USE_SAFE_ALLOCA; char *buffer = SAFE_ALLOCA (to_read); ssize_t n = read (fd, buffer, to_read); if (n < 0) report_file_notify_error ("Error while reading file system events", Qnil); struct input_event event; EVENT_INIT (event); event.kind = FILE_NOTIFY_EVENT; for (ssize_t i = 0; i < n; ) { struct inotify_event *ev = (struct inotify_event *) &buffer[i]; Lisp_Object descriptor = INTEGER_TO_CONS (ev->wd); Lisp_Object prevtail = find_descriptor (descriptor); if (! NILP (prevtail)) { Lisp_Object tail = CONSP (prevtail) ? XCDR (prevtail) : watch_list; for (Lisp_Object watches = XCDR (XCAR (tail)); ! NILP (watches); watches = XCDR (watches)) { event.arg = inotifyevent_to_event (XCAR (watches), ev); if (!NILP (event.arg)) kbd_buffer_store_event (&event); } /* If event was removed automatically: Drop it from watch list. */ if (ev->mask & IN_IGNORED) remove_descriptor (prevtail, true); } i += sizeof (*ev) + ev->len; } SAFE_FREE (); }
static void x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, Lisp_Object frame) { struct frame *f = XFRAME (frame); struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); Time timestamp = last_event_timestamp; OSStatus err; Selection sel; struct gcpro gcpro1, gcpro2; Lisp_Object rest, handler_fn, value, target_type; GCPRO2 (selection_name, selection_value); block_input (); err = mac_get_selection_from_symbol (selection_name, 1, &sel); if (err == noErr && sel) { /* Don't allow a quit within the converter. When the user types C-g, he would be surprised if by luck it came during a converter. */ ptrdiff_t count = SPECPDL_INDEX (); specbind (Qinhibit_quit, Qt); for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest)) { if (!(CONSP (XCAR (rest)) && (target_type = XCAR (XCAR (rest)), SYMBOLP (target_type)) && mac_valid_selection_target_p (target_type) && (handler_fn = XCDR (XCAR (rest)), SYMBOLP (handler_fn)))) continue; if (!NILP (handler_fn)) value = call3 (handler_fn, selection_name, target_type, selection_value); else value = Qnil; if (NILP (value)) continue; if (mac_valid_selection_value_p (value, target_type)) err = mac_put_selection_value (sel, target_type, value); else if (CONSP (value) && EQ (XCAR (value), target_type) && mac_valid_selection_value_p (XCDR (value), target_type)) err = mac_put_selection_value (sel, target_type, XCDR (value)); } unbind_to (count, Qnil); } unblock_input (); UNGCPRO; if (sel && err != noErr) error ("Can't set selection"); /* Now update the local cache */ { Lisp_Object selection_data; Lisp_Object ownership_info; Lisp_Object prev_value; if (sel) { block_input (); ownership_info = mac_get_selection_ownership_info (sel); unblock_input (); } else ownership_info = Qnil; /* dummy value for local-only selection */ selection_data = list5 (selection_name, selection_value, INTEGER_TO_CONS (timestamp), frame, ownership_info); prev_value = LOCAL_SELECTION (selection_name, dpyinfo); tset_selection_alist (dpyinfo->terminal, Fcons (selection_data, dpyinfo->terminal->Vselection_alist)); /* If we already owned the selection, remove the old selection data. Don't use Fdelq as that may QUIT. */ if (!NILP (prev_value)) { /* We know it's not the CAR, so it's easy. */ Lisp_Object rest = dpyinfo->terminal->Vselection_alist; for (; CONSP (rest); rest = XCDR (rest)) if (EQ (prev_value, Fcar (XCDR (rest)))) { XSETCDR (rest, XCDR (XCDR (rest))); break; } } } }