emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: address@hidden: modification hooks called only once in c-mode]


From: Chong Yidong
Subject: Re: address@hidden: modification hooks called only once in c-mode]
Date: Fri, 10 Aug 2007 20:46:37 -0400
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1.50 (gnu/linux)

Richard Stallman <address@hidden> writes:

> Would someone please DTRT, then ack?
> If the fix is simple enough, it should be installed in Emacs 22.
> ....
>
> (defun test-bug-hook (overlay afterp beg end &optional r)
>   (message "%s hook called" (if afterp "after" "before")))
>
> (defun test-bug ()
>   (let ((beg (point))
>         ov)
>     (insert "foobar")
>     (setq ov (make-overlay beg (point)))
>     (overlay-put ov 'face 'highlight)
>     (overlay-put ov 'insert-in-front-hooks '(test-bug-hook))))
>
> 1) Create a new buffer in c-mode, evaluate (test-bug), and insert a char
> before the overlay.
>
> Result:
> before hook called
>
> The hook is never called after the change.

The problem is in report_overlay_modification in buffer.c.  This
function, which is called both before and after a modification,
compiles a list of modification-hooks to run and executes them.  When
called before modification, it first does

      last_overlay_modification_hooks_used = 0;

to reset the list of modification hooks to run.  

The bug arises when you have an after-change hook that does buffer
changes (in this case, this is c-after-change, which calls
c-invalidate-sws-region-after).  The sequence of events is:

 1. User issues command to modify the buffer.

 2. Before the change is applied, report_overlay_modification is
    called.  It resets last_overlay_modification_hooks_used to zero,
    then compiles a list of hooks to run.  This includes both the
    insert-in-front hook and the after-change hook.

 3. The insert-in-front hook runs.

 4. The buffer modification is applies.

 5. The after-change hook runs, modifying the buffer elsewhere.

 6. This results in report_overlay_modification being called, which
    resets last_overlay_modification_hooks_used to zero.  The
    insert-in-front hook, which was scheduled to run next, gets rubbed
    out.

One simple fix is to bind inhibit-modification-hooks in
c-after-change.

A deeper fix would be to make report_overlay_modification check if it
is being called in a modification hook, and take steps to prevent
scheduled hooks from being rubbed out.  I'm not sure this behavior is
significantly more "correct" than the existing one, however; it may be
better to leave it as is.

In either case, I'd suggest not putting the fix for this in Emacs
22.2.  The first fix can cause subtle problems since c-after-change is
a core part of cc-mode, and the second one is also somewhat delicate.
It can go in the trunk, and be merged into the branch for 22.3 if no
problems are found.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]