diff src/extents.c @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents 56c54cf7c5b6
children 1ce6082ce73f
line wrap: on
line diff
--- a/src/extents.c	Mon Aug 13 09:00:04 2007 +0200
+++ b/src/extents.c	Mon Aug 13 09:02:59 2007 +0200
@@ -445,6 +445,7 @@
 /* Qhighlight defined in general.c */
 Lisp_Object Qunique;
 Lisp_Object Qduplicable;
+Lisp_Object Qreplicating;
 Lisp_Object Qdetachable;
 Lisp_Object Qpriority;
 Lisp_Object Qmouse_face;
@@ -1578,8 +1579,7 @@
    descendants. */
 
 static void
-extent_changed_for_redisplay (EXTENT extent, int descendants_too,
-			      int invisibility_change)
+extent_changed_for_redisplay (EXTENT extent, int descendants_too)
 {
   Lisp_Object object;
   Lisp_Object rest;
@@ -1598,8 +1598,7 @@
 	     if there are any circularities here, so we sure as hell better
 	     ensure that there aren't. */
 	  LIST_LOOP (rest, XWEAK_LIST_LIST (children))
-	    extent_changed_for_redisplay (XEXTENT (XCAR (rest)), 1,
-					  invisibility_change);
+	    extent_changed_for_redisplay (XEXTENT (XCAR (rest)), 1);
 	}
     }
 
@@ -1628,8 +1627,6 @@
     b = XBUFFER (object);
     BUF_FACECHANGE (b)++;
     MARK_EXTENTS_CHANGED;
-    if (invisibility_change)
-      MARK_CLIP_CHANGED;
     buffer_extent_signal_changed_region (b,
 					 extent_endpoint_bufpos (extent, 0),
 					 extent_endpoint_bufpos (extent, 1));
@@ -1642,16 +1639,14 @@
    the extent has any displayable attributes. */
 
 static void
-extent_maybe_changed_for_redisplay (EXTENT extent, int descendants_too,
-				    int invisibility_change)
+extent_maybe_changed_for_redisplay (EXTENT extent, int descendants_too)
 {
   /* Retrieve the ancestor for efficiency */
   EXTENT anc = extent_ancestor (extent);
   if (!NILP (extent_face (anc)) || !NILP (extent_begin_glyph (anc)) ||
       !NILP (extent_end_glyph (anc)) || !NILP (extent_mouse_face (anc)) ||
-      !NILP (extent_invisible (anc)) || invisibility_change)
-    extent_changed_for_redisplay (extent, descendants_too,
-				  invisibility_change);
+      !NILP (extent_invisible (anc)))
+    extent_changed_for_redisplay (extent, descendants_too);
 }
 
 static EXTENT
@@ -1799,8 +1794,7 @@
   extent_list_insert (el, extent);
   soe_insert (extent_object (extent), extent);
   /* only this extent changed */
-  extent_maybe_changed_for_redisplay (extent, 0,
-				      !NILP (extent_invisible (extent)));
+  extent_maybe_changed_for_redisplay (extent, 0);
 }
 
 static void
@@ -1813,8 +1807,7 @@
   el = extent_extent_list (extent);
 
   /* call this before messing with the extent. */
-  extent_maybe_changed_for_redisplay (extent, 0,
-				      !NILP (extent_invisible (extent)));
+  extent_maybe_changed_for_redisplay (extent, 0);
   extent_list_delete (el, extent);
   soe_delete (extent_object (extent), extent);
   set_extent_start (extent, -1);
@@ -1975,10 +1968,8 @@
       assert (!extent_detached_p (after));
     }
 
-  el = buffer_or_string_extent_list (obj);
-  if (!el || !extent_list_num_els(el))
+  if (!buffer_or_string_extent_list (obj))
     return;
-  el = 0;
 
   st = buffer_or_string_bytind_to_memind (obj, from);
   en = buffer_or_string_bytind_to_memind (obj, to);
@@ -2324,9 +2315,8 @@
 #endif
   el = buffer_or_string_extent_list (obj);
 
-  if (!el || !extent_list_num_els(el))
+  if (!el)
     return;
-
   /* IMPORTANT! Compute the starting positions of the extents to
      modify BEFORE doing any modification!  Otherwise the starting
      position for the second time through the loop might get
@@ -2526,7 +2516,7 @@
     buffer_or_string_absolute_end_byte (obj) :
       buffer_or_string_accessible_end_byte (obj);
 
-  if (!bel || !extent_list_num_els(bel))
+  if (!bel)
     return limit;
 
   sel = buffer_or_string_stack_of_extents_force (obj)->extents;
@@ -2566,7 +2556,7 @@
     buffer_or_string_absolute_begin_byte (obj) :
       buffer_or_string_accessible_begin_byte (obj);
 
-  if (!bel || !extent_list_num_els(bel))
+  if (!bel)
     return limit;
 
   sel = buffer_or_string_stack_of_extents_force (obj)->extents;
@@ -2966,11 +2956,12 @@
   if (!NILP (extent_read_only (anc))) *bp++ = '%';
   if (!NILP (extent_mouse_face (anc))) *bp++ = 'H';
   if (extent_unique_p (anc)) *bp++ = 'U';
+  else if (extent_replicating_p (anc)) *bp++ = 'R';
   else if (extent_duplicable_p (anc)) *bp++ = 'D';
   if (!NILP (extent_invisible (anc))) *bp++ = 'I';
 
   if (!NILP (extent_read_only (anc)) || !NILP (extent_mouse_face (anc)) ||
-      extent_unique_p (anc) ||
+      extent_unique_p (anc) || extent_replicating_p (anc) ||
       extent_duplicable_p (anc) || !NILP (extent_invisible (anc)))
     *bp++ = ' ';
 
@@ -3519,15 +3510,7 @@
       e->flags.has_parent = 1;
     }
   /* changing the parent also changes the properties of all children. */
-  {
-    int old_invis = (!NILP (cur_parent) &&
-		     !NILP (extent_invisible (XEXTENT (cur_parent))));
-    int new_invis = (!NILP (parent) &&
-		     !NILP (extent_invisible (XEXTENT (parent))));
-
-    extent_maybe_changed_for_redisplay (e, 1, new_invis != old_invis);
-  }
-
+  extent_maybe_changed_for_redisplay (e, 1);
   return Qnil;
 }
 
@@ -4020,7 +4003,7 @@
 on them will be visited.  If optional arg VALUE is non-nil, only extents
 whose value for that property is `eq' to VALUE will be visited.
 */
-       (function, object, from, to, maparg, flags, property, value))
+  (function, object, from, to, maparg, flags, property, value))
 {
   /* This function can GC */
   struct slow_map_extents_arg closure;
@@ -4379,7 +4362,7 @@
 considered is ignored.  If you want to pay attention to those properties,
 you should use `map-extents', which gives you more control.
 */
-       (pos, object, property, before, at_flag))
+     (pos, object, property, before, at_flag))
 {
   Bytind position;
   EXTENT before_extent;
@@ -4428,7 +4411,6 @@
   if (CONSP (closure->iro) && !NILP (Fmemq (prop, closure->iro)))
     return 0;
 
-#if 0 /* Nobody seems to care for this any more -sb */
   /* Allow deletion if the extent is completely contained in
      the region being deleted.
      This is important for supporting tokens which are internally
@@ -4440,7 +4422,6 @@
       extent_start (extent) >= closure->start &&
       extent_end (extent) <= closure->end)
     return 0;
-#endif
 
   while (1)
     Fsignal (Qbuffer_read_only, (list1 (closure->object)));
@@ -4626,7 +4607,7 @@
   if (!EQ (extent_invisible (extent), value))
     {
       set_extent_invisible_1 (extent, value);
-      extent_changed_for_redisplay (extent, 1, 1);
+      extent_changed_for_redisplay (extent, 1);
     }
 }
 
@@ -4783,16 +4764,18 @@
 */
        (extent, face))
 {
-  EXTENT e = decode_extent(extent, 0);
+  EXTENT e;
   Lisp_Object orig_face = face;
 
+  CHECK_EXTENT (extent);
+  e = XEXTENT (extent);
   /* retrieve the ancestor for efficiency and proper redisplay noting. */
   e = extent_ancestor (e);
 
   face = memoize_extent_face_internal (face);
 
   extent_face (e) = face;
-  extent_changed_for_redisplay (e, 1, 0);
+  extent_changed_for_redisplay (e, 1);
 
   return orig_face;
 }
@@ -4832,7 +4815,7 @@
   face = memoize_extent_face_internal (face);
 
   set_extent_mouse_face (e, face);
-  extent_changed_for_redisplay (e, 1, 0);
+  extent_changed_for_redisplay (e, 1);
 
   return orig_face;
 }
@@ -4854,7 +4837,7 @@
       extent_end_glyph_layout (extent) = layout;
     }
 
-  extent_changed_for_redisplay (extent, 1, 0);
+  extent_changed_for_redisplay (extent, 1);
 }
 
 static Lisp_Object
@@ -4956,7 +4939,7 @@
   EXTENT e = decode_extent (extent, 0);
   e = extent_ancestor (e);
   extent_begin_glyph_layout (e) = symbol_to_glyph_layout (layout);
-  extent_maybe_changed_for_redisplay (e, 1, 0);
+  extent_maybe_changed_for_redisplay (e, 1);
   return layout;
 }
 
@@ -4969,7 +4952,7 @@
   EXTENT e = decode_extent (extent, 0);
   e = extent_ancestor (e);
   extent_end_glyph_layout (e) = symbol_to_glyph_layout (layout);
-  extent_maybe_changed_for_redisplay (e, 1, 0);
+  extent_maybe_changed_for_redisplay (e, 1);
   return layout;
 }
 
@@ -5008,7 +4991,7 @@
   CHECK_INT (pri);
   e = extent_ancestor (e);
   set_extent_priority (e, XINT (pri));
-  extent_maybe_changed_for_redisplay (e, 1, 0);
+  extent_maybe_changed_for_redisplay (e, 1);
   return pri;
 }
 
@@ -5092,13 +5075,26 @@
                     string into a buffer, the extents are copied back
                     into the buffer.
                     
- unique             Meaningful only in conjunction with `duplicable'.
-                    When this is set, there may be only one instance
-                    of this extent attached at a time: if it is copied
-                    to the kill ring and then yanked, the extent is
-                    not copied.  If, however, it is killed (removed
-                    from the buffer) and then yanked, it will be
-                    re-attached at the new position.
+ replicating        Meaningful only in conjunction with `duplicable'.
+                    If this flag is set, extents that are copied from
+                    buffers into strings are made children of the
+                    original extent.  When the string is pasted back
+                    into a buffer, the same extent (i.e. the `eq'
+                    predicate applies) that was originally in the
+                    buffer will be used if possible -- i.e. if the
+                    extent is detached or the paste location abuts or
+                    overlaps the extent.  This behavior is compatible
+                    with the old "extent replica" behavior and was
+                    apparently required by Energize.
+                    
+ unique             Meaningful only in conjunction with `duplicable'
+                    and `replicating'.  When this is set, there may be
+                    only one instance of this extent attached at a
+                    time: if it is copied to the kill ring and then
+                    yanked, the extent is not copied.  If, however, it
+                    is killed (removed from the buffer) and then
+                    yanked, it will be re-attached at the new
+                    position.
                     
  invisible          If the value is non-nil, text under this extent
                     may be treated as not present for the purpose of
@@ -5154,7 +5150,7 @@
                     `inside-margin', or `outside-margin') of the extent's
                     begin glyph.
 
- end-glyph-layout The layout policy of the extent's end glyph.
+ end-glyph-layout   The layout policy of the extent's end glyph.
 */
        (extent, property, value))
 {
@@ -5168,6 +5164,8 @@
     extent_unique_p (e) = !NILP (value);
   else if (EQ (property, Qduplicable))
     extent_duplicable_p (e) = !NILP (value);
+  else if (EQ (property, Qreplicating))
+    extent_replicating_p (e) = !NILP (value);
   else if (EQ (property, Qinvisible))
     set_extent_invisible (e, value);
   else if (EQ (property, Qdetachable))
@@ -5254,6 +5252,7 @@
   else if (EQ (property, Qend_open))	 RETURN_FLAG (end_open);
   else if (EQ (property, Qunique))	 RETURN_FLAG (unique);
   else if (EQ (property, Qduplicable))	 RETURN_FLAG (duplicable);
+  else if (EQ (property, Qreplicating))	 RETURN_FLAG (replicating);
   else if (EQ (property, Qdetachable))	 RETURN_FLAG (detachable);
 #undef RETURN_FLAG
   /* Support (but don't document...) the obvious antonyms. */
@@ -5356,6 +5355,7 @@
   result = Fcons (sym, Fcons (Qt, result))
   CONS_FLAG (end_open, Qend_open);
   CONS_FLAG (start_open, Qstart_open);
+  CONS_FLAG (replicating, Qreplicating);
   CONS_FLAG (detachable, Qdetachable);
   CONS_FLAG (duplicable, Qduplicable);
   CONS_FLAG (unique, Qunique);
@@ -5388,14 +5388,14 @@
     {
       /* do not recurse on descendants.  Only one extent is highlighted
 	 at a time. */
-      extent_changed_for_redisplay (XEXTENT (Vlast_highlighted_extent), 0, 0);
+      extent_changed_for_redisplay (XEXTENT (Vlast_highlighted_extent), 0);
     }
   Vlast_highlighted_extent = Qnil;
   if (!NILP (extent_obj)
       && BUFFERP (extent_object (XEXTENT (extent_obj)))
       && highlight_p)
     {
-      extent_changed_for_redisplay (XEXTENT (extent_obj), 0, 0);
+      extent_changed_for_redisplay (XEXTENT (extent_obj), 0);
       Vlast_highlighted_extent = extent_obj;
     }
 }
@@ -5615,6 +5615,14 @@
 				     end + closure->from))
 	return 0;
       e = copy_extent (extent, start, end, closure->string);
+      if (extent_replicating_p (extent))
+	{
+	  Lisp_Object e_obj = Qnil, extent_obj = Qnil;
+
+	  XSETEXTENT (e_obj, e);
+	  XSETEXTENT (extent_obj, extent);
+	  Fset_extent_parent (e_obj, extent_obj);
+	}
     }
 
   return 0;
@@ -5682,12 +5690,62 @@
   if (!extent_duplicable_p (extent))
     return 0;
 
-  if (!inside_undo &&
-      !run_extent_paste_function (extent, new_start, new_end,
-				  closure->buffer))
-    return 0;
-  copy_extent (extent, new_start, new_end, closure->buffer);
-
+  if (!extent_replicating_p (extent))
+    {
+      if (!inside_undo &&
+	  !run_extent_paste_function (extent, new_start, new_end,
+				      closure->buffer))
+	return 0;
+      copy_extent (extent, new_start, new_end, closure->buffer);
+    }
+  else
+    {
+      Bytind parstart = 0;
+      Bytind parend = 0;
+      Lisp_Object parent_obj = extent_parent (extent);
+      EXTENT parent;
+
+      if (!EXTENTP (parent_obj))
+	return 0;
+      parent = XEXTENT (parent_obj);
+      if (!EXTENT_LIVE_P (parent))
+	return 0;
+
+      if (!extent_detached_p (parent))
+	{
+	  parstart = extent_endpoint_bytind (parent, 0);
+	  parend = extent_endpoint_bytind (parent, 1);
+	}
+
+/* #### remove this crap */
+#ifdef ENERGIZE
+      /* Energize extents like toplevel-forms can only be pasted 
+	 in the buffer they come from.  This should be parametrized
+	 in the generic extent objects.  Right now just silently
+	 skip the extents if it's not from the same buffer.
+	 */
+      if (!EQ (extent_object (parent), closure->buffer)
+	  && energize_extent_data (parent))
+	return 0;
+#endif
+	  
+      /* If this is a `unique' extent, and it is currently attached
+	 somewhere other than here (non-overlapping), then don't copy
+	 it (that's what `unique' means).  If however it is detached,
+	 or if we are inserting inside/adjacent to the original
+	 extent, then insert_extent() will simply reattach it, which
+	 is what we want.
+	 */
+      if (extent_unique_p (parent)
+	  && !extent_detached_p (parent)
+	  && (!EQ (extent_object (parent), closure->buffer)
+	      || parend > new_end
+	      || parstart < new_start))
+	return 0;
+  
+      insert_extent (parent, new_start, new_end,
+		     closure->buffer, !inside_undo);
+    }
   return 0;
 }
 
@@ -5740,6 +5798,13 @@
   struct copy_string_extents_1_arg *closure = 
     (struct copy_string_extents_1_arg *) arg;
 
+  if (extent_replicating_p (extent) &&
+      EQ (extent_parent (extent), closure->parent_in_question))
+    {
+      closure->found_extent = extent;
+      return 1; /* stop mapping */
+    }
+
   return 0;
 }
 
@@ -5763,6 +5828,35 @@
   new_start = old_start + closure->new_pos - closure->old_pos;
   new_end = old_end + closure->new_pos - closure->old_pos;
 
+  if (extent_replicating_p (extent))
+    {
+      struct copy_string_extents_1_arg closure_1;
+
+      closure_1.parent_in_question = extent_parent (extent);
+      closure_1.found_extent = 0;
+
+      /* When adding a replicating extent, we need to make sure
+	 that there isn't an existing replicating extent referring
+	 to the same parent extent that abuts or overlaps.  If so,
+	 we merge with that extent rather than adding anew. */
+      map_extents_bytind (closure->old_pos, closure->old_pos + closure->length,
+			  copy_string_extents_1_mapper,
+			  (void *) &closure, closure->new_string, 0,
+			  /* get all extents that abut the region */
+			  ME_END_CLOSED | ME_ALL_EXTENTS_CLOSED);
+      if (closure_1.found_extent)
+	{
+	  Bytecount exstart =
+	    extent_endpoint_bytind (closure_1.found_extent, 0);
+	  Bytecount exend =
+	    extent_endpoint_bytind (closure_1.found_extent, 1);
+	  exstart = min (exstart, new_start);
+	  exend = max (exend, new_end);
+	  set_extent_endpoints (closure_1.found_extent, exstart, exend, Qnil);
+	  return 0;
+	}
+    }
+      
   copy_extent (extent,
 	       old_start + closure->new_pos - closure->old_pos,
 	       old_end + closure->new_pos - closure->old_pos,
@@ -6184,9 +6278,6 @@
 		      ME_ALL_EXTENTS_CLOSED | ME_END_CLOSED |
 		      /* it might QUIT or error if the user has
 			 fucked with the extent plist. */
-		      /* #### dmoore - I think this should include
-			 ME_MIGHT_MOVE_SOE, since the callback function
-			 might recurse back into map_extents_bytind. */
 		      ME_MIGHT_THROW |
 		      ME_MIGHT_MODIFY_EXTENTS);
 
@@ -6374,15 +6465,9 @@
   if (NILP (prop))
     signal_simple_error ("internal error: no text-prop", extent);
   val = Fextent_property (extent, prop, Qnil);
-#if 0
-  /* removed by bill perry, 2/9/97
-  ** This little bit of code would not allow you to have a text property
-  ** with a value of Qnil.  This is bad bad bad.
-  */
   if (NILP (val))
     signal_simple_error_2 ("internal error: no text-prop",
 			   extent, prop);
-#endif
   Fput_text_property (from, to, prop, val, Qnil);
   return Qnil; /* important! */
 }
@@ -6574,6 +6659,7 @@
   /* defsymbol (&Qhighlight, "highlight"); in faces.c */
   defsymbol (&Qunique, "unique");
   defsymbol (&Qduplicable, "duplicable");
+  defsymbol (&Qreplicating, "replicating");
   defsymbol (&Qdetachable, "detachable");
   defsymbol (&Qpriority, "priority");
   defsymbol (&Qmouse_face, "mouse-face");