diff --git a/src/editfns.c b/src/editfns.c index 8dfea1f..333db38 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -500,6 +500,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/keyboard.c b/src/keyboard.c index de4e1c5..7c198e9 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1978,6 +1978,10 @@ command_loop_1 () && !already_adjusted) adjust_point_for_property (last_point_position, MODIFF != prev_modiff); + if (current_buffer == prev_buffer + && NILP (Vinhibit_point_motion_hooks)) + run_point_motion_hooks(); + /* Install chars successfully executed in kbd macro. */ if (!NILP (current_kboard->defining_kbd_macro) @@ -1990,6 +1994,98 @@ command_loop_1 () } } +/* Runs 'point-motion hooks on text properties and overlays.*/ +void +run_point_motion_hooks () +{ + extern Lisp_Object Qpoint_motion, Qwindow; + + static Lisp_Object* overlay_prev_vec; + static Lisp_Object prev_text_prop; + static int noverlays_prev; + static Lisp_Object prev_window; + + int i, j, noverlays_cur; + Lisp_Object *overlay_cur_vec; + Lisp_Object point_motion, overlay_window; + + if ( !NILP (Feq (prev_window, Fselected_window()))) + { + /* 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; + } + prev_window = Fselected_window(); +} + + extern Lisp_Object Qcomposition, Qdisplay; /* Adjust point to a boundary of a region that has such a property @@ -8101,10 +8197,10 @@ parse_menu_item (item, notreal, inmenubar) && !(SYMBOLP (def) && EQ (tem, XSYMBOL (def)->function)))) keys = Qnil; } - + if (NILP (keys)) keys = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qnil); - + if (!NILP (keys)) { tem = Fkey_description (keys, Qnil); @@ -8119,7 +8215,7 @@ parse_menu_item (item, notreal, inmenubar) /* tem = concat3 (build_string (" ("), tem, build_string (")")); */ } } - + /* If we only want to precompute equivalent key bindings, stop here. */ if (notreal) diff --git a/src/textprop.c b/src/textprop.c index e82af12..02a66c0 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -54,6 +54,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; @@ -2349,6 +2350,7 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and Qpoint_left = intern ("point-left"); staticpro (&Qpoint_entered); Qpoint_entered = intern ("point-entered"); + Qpoint_motion = intern ("point-motion"); defsubr (&Stext_properties_at); defsubr (&Sget_text_property);