(Qbefore_string, Qafter_string): New vars.
authorKarl Heuer <kwzh@gnu.org>
Fri, 5 May 1995 00:34:00 +0000 (00:34 +0000)
committerKarl Heuer <kwzh@gnu.org>
Fri, 5 May 1995 00:34:00 +0000 (00:34 +0000)
(syms_of_buffer): Initialize and staticpro them.
(cmp_for_strings, overlay_strings): New functions.

src/buffer.c

index 6ba8266..6cf2aea 100644 (file)
@@ -141,7 +141,7 @@ Lisp_Object Qget_file_buffer;
 
 Lisp_Object Qoverlayp;
 
-Lisp_Object Qpriority, Qwindow, Qevaporate;
+Lisp_Object Qpriority, Qwindow, Qevaporate, Qbefore_string, Qafter_string;
 
 Lisp_Object Qmodification_hooks;
 Lisp_Object Qinsert_in_front_hooks;
@@ -1274,7 +1274,7 @@ set_buffer_internal (b)
 }
 
 /* Switch to buffer B temporarily for redisplay purposes.
-   This avoids certain things thatdon't need to be done within redisplay.  */
+   This avoids certain things that don't need to be done within redisplay.  */
 
 void
 set_buffer_temp (b)
@@ -1534,7 +1534,7 @@ swap_out_buffer_local_variables (b)
    Store in *LEN_PTR the size allocated for the vector.
    Store in *NEXT_PTR the next position after POS where an overlay starts,
      or ZV if there are no more overlays.
-   Store in *PREV_PTR the previous position after POS where an overlay ends,
+   Store in *PREV_PTR the previous position before POS where an overlay ends,
      or BEGV if there are no previous overlays.
    NEXT_PTR and/or PREV_PTR may be 0, meaning don't store that info.
 
@@ -1776,6 +1776,232 @@ sort_overlays (overlay_vec, noverlays, w)
   return (noverlays);
 }
 \f
+struct sortstr
+{
+  Lisp_Object string;
+  int size;
+  int priority;
+};
+
+/* A comparison function suitable for passing to qsort.  */
+static int
+cmp_for_strings (as1, as2)
+     char *as1, *as2;
+{
+  struct sortstr *s1 = (struct sortstr *)as1;
+  struct sortstr *s2 = (struct sortstr *)as2;
+  if (s1->size != s2->size)
+    return s2->size - s1->size;
+  if (s1->priority != s2->priority)
+    return s1->priority - s2->priority;
+  return 0;
+}
+
+/* Buffers for storing the overlays touching a given position.
+   These are expanded as needed, but never freed.  */
+static struct sortstr *overlay_heads, *overlay_tails;
+static char *overlay_str_buf;
+
+/* Allocated length of those buffers.  */
+static int overlay_heads_len, overlay_tails_len, overlay_str_len;
+
+/* Return the concatenation of the strings associated with overlays that
+   begin or end at POS, ignoring overlays that are specific to a window
+   other than W.  The strings are concatenated in the appropriate order:
+   shorter overlays nest inside longer ones, and higher priority inside
+   lower.  Returns the string length, and stores the contents indirectly
+   through PSTR, if that variable is non-null.  The string may be
+   overwritten by subsequent calls.  */
+int
+overlay_strings (pos, w, pstr)
+     int pos;
+     struct window *w;
+     char **pstr;
+{
+  Lisp_Object ov, overlay, window, str, tem;
+  int ntail = 0, nhead = 0;
+  int total = 0;
+  int startpos, endpos;
+
+  for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCONS (ov)->cdr)
+    {
+      overlay = XCONS (ov)->car;
+      if (!OVERLAYP (overlay))
+       abort ();
+
+      startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
+      endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
+      if (endpos < pos)
+       break;
+      if (endpos != pos && startpos != pos)
+       continue;
+      window = Foverlay_get (overlay, Qwindow);
+      if (WINDOWP (window) && XWINDOW (window) != w)
+       continue;
+      if (endpos == pos)
+       {
+         str = Foverlay_get (overlay, Qafter_string);
+         if (STRINGP (str))
+           {
+             if (ntail == overlay_tails_len)
+               {
+                 if (! overlay_tails)
+                   {
+                     overlay_tails_len = 5;
+                     overlay_tails = ((struct sortstr *)
+                                      xmalloc (5 * sizeof (struct sortstr)));
+                   }
+                 else
+                   {
+                     overlay_tails_len *= 2;
+                     overlay_tails = ((struct sortstr *)
+                                      xrealloc ((overlay_tails_len
+                                                 * sizeof (struct sortstr))));
+                   }
+               }
+             overlay_tails[ntail].string = str;
+             overlay_tails[ntail].size = endpos - startpos;
+             tem = Foverlay_get (overlay, Qpriority);
+             overlay_tails[ntail].priority = (INTEGERP (tem) ? XINT (tem) : 0);
+             ntail++;
+             total += XSTRING (str)->size;
+           }
+       }
+      if (startpos == pos)
+       {
+         str = Foverlay_get (overlay, Qbefore_string);
+         if (STRINGP (str))
+           {
+             if (nhead == overlay_heads_len)
+               {
+                 if (! overlay_heads)
+                   {
+                     overlay_heads_len = 5;
+                     overlay_heads = ((struct sortstr *)
+                                      xmalloc (5 * sizeof (struct sortstr)));
+                   }
+                 else
+                   {
+                     overlay_heads_len *= 2;
+                     overlay_heads = ((struct sortstr *)
+                                      xrealloc ((overlay_heads_len
+                                                 * sizeof (struct sortstr))));
+                   }
+               }
+             overlay_heads[nhead].string = str;
+             overlay_heads[nhead].size = endpos - startpos;
+             tem = Foverlay_get (overlay, Qpriority);
+             overlay_heads[nhead].priority = (INTEGERP (tem) ? XINT (tem) : 0);
+             nhead++;
+             total += XSTRING (str)->size;
+           }
+       }
+    }
+  for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCONS (ov)->cdr)
+    {
+      overlay = XCONS (ov)->car;
+      if (!OVERLAYP (overlay))
+       abort ();
+
+      startpos = OVERLAY_POSITION (OVERLAY_START (overlay));
+      endpos = OVERLAY_POSITION (OVERLAY_END (overlay));
+      if (startpos > pos)
+       break;
+      if (endpos == pos)
+       {
+         str = Foverlay_get (overlay, Qafter_string);
+         if (STRINGP (str))
+           {
+             if (ntail == overlay_tails_len)
+               {
+                 if (! overlay_tails)
+                   {
+                     overlay_tails_len = 5;
+                     overlay_tails = ((struct sortstr *)
+                                      xmalloc (5 * sizeof (struct sortstr)));
+                   }
+                 else
+                   {
+                     overlay_tails_len *= 2;
+                     overlay_tails = ((struct sortstr *)
+                                      xrealloc ((overlay_tails_len
+                                                 * sizeof (struct sortstr))));
+                   }
+               }
+             overlay_tails[ntail].string = str;
+             overlay_tails[ntail].size = endpos - startpos;
+             tem = Foverlay_get (overlay, Qpriority);
+             overlay_tails[ntail].priority = (INTEGERP (tem) ? XINT (tem) : 0);
+             ntail++;
+             total += XSTRING (str)->size;
+           }
+       }
+      if (startpos == pos)
+       {
+         str = Foverlay_get (overlay, Qbefore_string);
+         if (STRINGP (str))
+           {
+             if (nhead == overlay_heads_len)
+               {
+                 if (! overlay_heads)
+                   {
+                     overlay_heads_len = 5;
+                     overlay_heads = ((struct sortstr *)
+                                      xmalloc (5 * sizeof (struct sortstr)));
+                   }
+                 else
+                   {
+                     overlay_heads_len *= 2;
+                     overlay_heads = ((struct sortstr *)
+                                      xrealloc ((overlay_heads_len
+                                                 * sizeof (struct sortstr))));
+                   }
+               }
+             overlay_heads[nhead].string = str;
+             overlay_heads[nhead].size = endpos - startpos;
+             tem = Foverlay_get (overlay, Qpriority);
+             overlay_heads[nhead].priority = (INTEGERP (tem) ? XINT (tem) : 0);
+             nhead++;
+             total += XSTRING (str)->size;
+           }
+       }
+    }
+  if (ntail > 1)
+    qsort (overlay_tails, ntail, sizeof (struct sortstr), cmp_for_strings);
+  if (nhead > 1)
+    qsort (overlay_heads, nhead, sizeof (struct sortstr), cmp_for_strings);
+  if (total)
+    {
+      int i;
+      char *p;
+
+      if (total > overlay_str_len)
+       {
+         if (! overlay_str_buf)
+           overlay_str_buf = (char *)xmalloc (total);
+         else
+           overlay_str_buf = (char *)xrealloc (overlay_str_buf, total);
+         overlay_str_len = total;
+       }
+      p = overlay_str_buf;
+      for (i = ntail; --i >= 0;)
+       {
+         tem = overlay_tails[i].string;
+         bcopy (XSTRING (tem)->data, p, XSTRING (tem)->size);
+         p += XSTRING (tem)->size;
+       }
+      for (i = 0; i < nhead; ++i)
+       {
+         tem = overlay_heads[i].string;
+         bcopy (XSTRING (tem)->data, p, XSTRING (tem)->size);
+         p += XSTRING (tem)->size;
+       }
+      if (pstr)
+       *pstr = overlay_str_buf;
+    }
+  return total;
+}
+\f
 /* Shift overlays in BUF's overlay lists, to center the lists at POS.  */
 
 void
@@ -2796,7 +3022,7 @@ init_buffer_once ()
   buffer_defaults.file_format = Qnil;
   buffer_defaults.overlays_before = Qnil;
   buffer_defaults.overlays_after = Qnil;
-  XSETFASTINT (buffer_defaults.overlay_center, 1);
+  XSETFASTINT (buffer_defaults.overlay_center, BEG);
 
   XSETFASTINT (buffer_defaults.tab_width, 8);
   buffer_defaults.truncate_lines = Qnil;
@@ -2948,6 +3174,10 @@ syms_of_buffer ()
   staticpro (&Qpriority);
   Qwindow = intern ("window");
   staticpro (&Qwindow);
+  Qbefore_string = intern ("before-string");
+  staticpro (&Qbefore_string);
+  Qafter_string = intern ("after-string");
+  staticpro (&Qafter_string);
 
   Qoverlayp = intern ("overlayp");