Sorry for taking so long on this - I ended up being pretty busy with school and couldn't work on it for a while. I added a function get_overlays_at_pos which will return a list of overlays active at the given position and buffer - the design is based on get_pos_property. Then at the end of command_loop_1, run_point_motion_hooks is called which will retrieve the overlays at the current position, run the 'point-motion' property with the old point, new point, and overlay, and then run property for all overlays which were just executed. The 'point-motion property is also executed for the text property at current point, and the previous point's text-property if it is different from the one at current point. The diff for this is below - let me know your thoughts. Thanks, Nathaniel Flath diff --git a/src/editfns.c b/src/editfns.c index e52c3c2..7f343f0 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -499,6 +499,48 @@ get_pos_property (position, prop, object) } } +/* Returns an array of overlays that are active at the indication position and buffer. + The lenght of the array will be stored in num_overlays. */ + +Lisp_Object* +get_overlays_at_pos (position, buffer, num_overlays ) + Lisp_Object position, buffer; + int* num_overlays; +{ + CHECK_NUMBER_COERCE_MARKER (position); + + if (NILP (buffer)) + XSETBUFFER (buffer, current_buffer); + + int posn = XINT (position); + int i, noverlays; + Lisp_Object* overlay_vec; + struct buffer *obuf = current_buffer; + set_buffer_temp (XBUFFER (buffer)); + + noverlays = overlays_around (posn, overlay_vec, 0); + overlay_vec = xmalloc (sizeof(Lisp_Object) * noverlays); + noverlays = overlays_around (posn, overlay_vec, noverlays); + noverlays = sort_overlays (overlay_vec, noverlays, NULL); + + set_buffer_temp (obuf); + for (i = 0; i < noverlays; i++) + { + Lisp_Object ol = overlay_vec[i]; + Lisp_Object start = OVERLAY_START (ol), finish = OVERLAY_END (ol); + if ((OVERLAY_POSITION (start) == posn + && XMARKER (start)->insertion_type == 1) + || (OVERLAY_POSITION (finish) == posn + && XMARKER (finish)->insertion_type == 0)) + { + overlay_vec[i] = overlay_vec[noverlays]; + noverlays--; i--; + } + } + *num_overlays = noverlays; + return overlay_vec; +} + /* Find the field surrounding POS in *BEG and *END. If POS is nil, the value of point is used instead. If BEG or END is null, means don't store the beginning or end of the field. diff --git a/src/textprop.c b/src/textprop.c index 0018088..5708040 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -53,6 +53,7 @@ Lisp_Object Qpoint_left; Lisp_Object Qpoint_entered; Lisp_Object Qcategory; Lisp_Object Qlocal_map; +Lisp_Object Qpoint_motion; /* Visual properties text (including strings) may have. */ Lisp_Object Qforeground, Qbackground, Qfont, Qunderline, Qstipple; @@ -2348,6 +2349,9 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and Qpoint_left = intern ("point-left"); staticpro (&Qpoint_entered); Qpoint_entered = intern ("point-entered"); + staticpro (&Qpoint_entered); + Qpoint_motion = intern ("point-motion"); + defsubr (&Stext_properties_at); defsubr (&Sget_text_property); diff --git a/src/keyboard.c b/src/keyboard.c index 35c338c..a375daf 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1989,6 +1993,93 @@ command_loop_1 () } } +/* Runs 'point-motion hooks on text properties and overlays.*/ + +void +run_point_motion_hooks () +{ + static Lisp_Object* overlay_prev_vec; + static Lisp_Object prev_text_prop; + static int noverlays_prev; + + int i, j, noverlays_cur; + Lisp_Object *overlay_cur_vec; + Lisp_Object point_motion, overlay_window; + extern Lisp_Object Qpoint_motion, Qwindow; + + /* Retrieves vector of overlays in current location and runs 'point-motion + hook for those whose 'window property allows it to be displayed */ + overlay_cur_vec = get_overlays_at_pos (make_number (current_buffer->pt), + current_buffer, + &noverlays_cur); + for (i = 0; i < noverlays_cur; i++) + { + point_motion = Foverlay_get (overlay_cur_vec[i], Qpoint_motion); + overlay_window = Foverlay_get (overlay_cur_vec[i], Qwindow); + if (!NILP (point_motion) && + (NILP (overlay_window) + || !NILP (Feq (overlay_window, Fselected_window())))) + { + call3 (point_motion, + make_number (last_point_position), + make_number (current_buffer->pt), + overlay_cur_vec[i]); + } + } + + /* Runs hooks for all overlays that the point used to be in but no longer is */ + for (i = 0; i < noverlays_prev; i++) + { + point_motion = Foverlay_get (overlay_prev_vec[i], Qpoint_motion); + overlay_window = Foverlay_get (overlay_prev_vec[i], Qwindow); + if (!NILP (point_motion) && + (NILP (overlay_window) + || !NILP (Feq (overlay_window, Fselected_window())))) + { + for (j = 0; noverlays_cur; j++) { + if (!NILP (Feq (overlay_prev_vec[i], overlay_cur_vec[j]))) + goto next; + } + + call3 (point_motion, + make_number (last_point_position), + make_number (current_buffer->pt), + overlay_prev_vec[i]); + next: i=i; + } + } + + /* Runs hook for current text property */ + point_motion = Fget_text_property (make_number (current_buffer->pt), + Qpoint_motion, + Qnil); + if (!NILP (point_motion)) + { + call3 (point_motion, + make_number (last_point_position), + make_number (current_buffer->pt), + Fcurrent_buffer()); + } + + /* Runs hook for previous text property if it is different than the current text property */ + if (prev_text_prop != 0 && !NILP (prev_text_prop)) { + if (NILP (Feq (prev_text_prop, point_motion))) + { + call3 (prev_text_prop, + make_number (last_point_position), + make_number (current_buffer->pt), + Fcurrent_buffer()); + } + } + + prev_text_prop = point_motion; + + /* Frees previous overlays and sets them to the current list */ + free (overlay_prev_vec); + overlay_prev_vec = overlay_cur_vec; + noverlays_prev = noverlays_cur; +} + extern Lisp_Object Qcomposition, Qdisplay; /* Adjust point to a boundary of a region that has such a property On Thu, Sep 24, 2009 at 10:26 AM, Stefan Monnier wrote: > > Never mind, since get_pos_property is a C function and not a Lisp one > this > > probably wouldn't work. > > That's OK. It can still return a list, or else an array. > But if it can return the overlays rather than the property's values, > then you could pass the overlay back to the hook functions, which would > probably be convnient for those functions. > > > Stefan >