]> git.eshelyaron.com Git - emacs.git/commitdiff
Update current buffer when changing text properties
authorPip Cet <pipcet@gmail.com>
Sat, 6 Jul 2019 15:21:04 +0000 (15:21 +0000)
committerEli Zaretskii <eliz@gnu.org>
Sat, 6 Jul 2019 16:20:53 +0000 (19:20 +0300)
* src/textprop.c (add_text_properties_1, set_text_properties)
(set_text_properties_1, Fremove_text_properties): Switch buffer if
necessary.  (Bug#36190)

* doc/lispref/text.texi (Examining Properties): Document performance
FIXME.

doc/lispref/text.texi
src/textprop.c

index c4fc5247a11c355635a797e27c353d5d752b234f..ca0dd6642d9c0ab75f75db12bf7c15ead9b9bc7b 100644 (file)
@@ -2800,7 +2800,7 @@ functions to examine the properties of a number of characters at once.
 
   These functions handle both strings and buffers.  Keep in mind that
 positions in a string start from 0, whereas positions in a buffer start
-from 1.
+from 1.  Passing a buffer other than the current buffer may be slow.
 
 @defun get-text-property pos prop &optional object
 This function returns the value of the @var{prop} property of the
index 9023f4efa06c8500b47b8e623e59cec1d885929f..44c333256a6af53f39b5c47cb3b6f1e612869cc9 100644 (file)
@@ -1142,6 +1142,18 @@ static Lisp_Object
 add_text_properties_1 (Lisp_Object start, Lisp_Object end,
                       Lisp_Object properties, Lisp_Object object,
                       enum property_set_type set_type) {
+  /* Ensure we run the modification hooks for the right buffer,
+     without switching buffers twice (bug 36190).  FIXME: Switching
+     buffers is slow and often unnecessary.  */
+  if (BUFFERP (object) && XBUFFER (object) != current_buffer)
+    {
+      ptrdiff_t count = SPECPDL_INDEX ();
+      record_unwind_current_buffer ();
+      set_buffer_internal (XBUFFER (object));
+      return unbind_to (count, add_text_properties_1 (start, end, properties,
+                                                     object, set_type));
+    }
+
   INTERVAL i, unchanged;
   ptrdiff_t s, len;
   bool modified = false;
@@ -1343,6 +1355,19 @@ Lisp_Object
 set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties,
                     Lisp_Object object, Lisp_Object coherent_change_p)
 {
+  /* Ensure we run the modification hooks for the right buffer,
+     without switching buffers twice (bug 36190).  FIXME: Switching
+     buffers is slow and often unnecessary.  */
+  if (BUFFERP (object) && XBUFFER (object) != current_buffer)
+    {
+      ptrdiff_t count = SPECPDL_INDEX ();
+      record_unwind_current_buffer ();
+      set_buffer_internal (XBUFFER (object));
+      return unbind_to (count,
+                       set_text_properties (start, end, properties,
+                                            object, coherent_change_p));
+    }
+
   INTERVAL i;
   bool first_time = true;
 
@@ -1413,6 +1438,20 @@ void
 set_text_properties_1 (Lisp_Object start, Lisp_Object end,
                       Lisp_Object properties, Lisp_Object object, INTERVAL i)
 {
+  /* Ensure we run the modification hooks for the right buffer,
+     without switching buffers twice (bug 36190).  FIXME: Switching
+     buffers is slow and often unnecessary.  */
+  if (BUFFERP (object) && XBUFFER (object) != current_buffer)
+    {
+      ptrdiff_t count = SPECPDL_INDEX ();
+      record_unwind_current_buffer ();
+      set_buffer_internal (XBUFFER (object));
+
+      set_text_properties_1 (start, end, properties, object, i);
+      unbind_to (count, Qnil);
+      return;
+    }
+
   INTERVAL prev_changed = NULL;
   ptrdiff_t s = XFIXNUM (start);
   ptrdiff_t len = XFIXNUM (end) - s;
@@ -1495,6 +1534,19 @@ Return t if any property was actually removed, nil otherwise.
 Use `set-text-properties' if you want to remove all text properties.  */)
   (Lisp_Object start, Lisp_Object end, Lisp_Object properties, Lisp_Object object)
 {
+  /* Ensure we run the modification hooks for the right buffer,
+     without switching buffers twice (bug 36190).  FIXME: Switching
+     buffers is slow and often unnecessary.  */
+  if (BUFFERP (object) && XBUFFER (object) != current_buffer)
+    {
+      ptrdiff_t count = SPECPDL_INDEX ();
+      record_unwind_current_buffer ();
+      set_buffer_internal (XBUFFER (object));
+      return unbind_to (count,
+                       Fremove_text_properties (start, end, properties,
+                                                object));
+    }
+
   INTERVAL i, unchanged;
   ptrdiff_t s, len;
   bool modified = false;
@@ -1607,6 +1659,20 @@ markers).  If OBJECT is a string, START and END are 0-based indices into it.
 Return t if any property was actually removed, nil otherwise.  */)
   (Lisp_Object start, Lisp_Object end, Lisp_Object list_of_properties, Lisp_Object object)
 {
+  /* Ensure we run the modification hooks for the right buffer,
+     without switching buffers twice (bug 36190).  FIXME: Switching
+     buffers is slow and often unnecessary.  */
+  if (BUFFERP (object) && XBUFFER (object) != current_buffer)
+    {
+      ptrdiff_t count = SPECPDL_INDEX ();
+      record_unwind_current_buffer ();
+      set_buffer_internal (XBUFFER (object));
+      return unbind_to (count,
+                       Fremove_list_of_text_properties (start, end,
+                                                        list_of_properties,
+                                                        object));
+    }
+
   INTERVAL i, unchanged;
   ptrdiff_t s, len;
   bool modified = false;