]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement display-time wrap/line-prefix feature
authorMiles Bader <miles@gnu.org>
Tue, 1 Jul 2008 09:39:28 +0000 (09:39 +0000)
committerMiles Bader <miles@gnu.org>
Tue, 1 Jul 2008 09:39:28 +0000 (09:39 +0000)
Revision: emacs@sv.gnu.org/emacs--devo--0--patch-1305

doc/lispref/ChangeLog
doc/lispref/display.texi
doc/lispref/text.texi
src/ChangeLog
src/dispextern.h
src/xdisp.c

index e4fa5529ac4cc046ee424af6d6168dd69477f087..17b3b61f73eb3334233f057f3682c786b913a6ce 100644 (file)
@@ -1,3 +1,8 @@
+2008-07-01  Miles Bader  <miles@gnu.org>
+
+       * text.texi (Special Properties):
+       * display.texi (Truncation): Add wrap-prefix and line-prefix.
+
 2008-06-28  Johan Bockgård  <bojohan@gnu.org>
 
        * display.texi (Other Image Types): Fix copy/paste error; say
index b09227d3f6cab853efd7c7c7ab5b36e6dace18bf..e7cb51072cc9e9a258090ef0c2e0cb255ab8f409 100644 (file)
@@ -191,6 +191,29 @@ If it is non-@code{nil}, these lines are truncated; otherwise,
   When horizontal scrolling (@pxref{Horizontal Scrolling}) is in use in
 a window, that forces truncation.
 
+@defvar wrap-prefix
+If this buffer-local variable is non-@code{nil}, the prefix it defines
+will be added at display-time to the beginning of every continuation
+line due to text wrapping (so if lines are truncated, the wrap-prefix
+is never used).  It may be a string, an image, or a stretch-glyph such
+as used by the `display' text-property.  @xref{Display Property}.
+
+A wrap-prefix may also be specified for regions of text using the
+@code{wrap-prefix} text-property (which takes precedence over the
+value of the @code{wrap-prefix} variable).  @xref{Special Properties}.
+@end defvar
+
+@defvar line-prefix
+If this buffer-local variable is non-@code{nil}, the prefix it defines
+will be added at display-time to the beginning of every
+non-continuation line It may be a string, an image, or a stretch-glyph
+such as used by the `display' text-property.  @xref{Display Property}.
+
+A line-prefix may also be specified for regions of text using the
+@code{line-prefix} text-property (which takes precedence over the
+value of the @code{line-prefix} variable).  @xref{Special Properties}.
+@end defvar
+
   If your buffer contains @emph{very} long lines, and you use
 continuation to display them, just thinking about them can make Emacs
 redisplay slow.  The column computation and indentation functions also
index b1a8653def5dd42072b0a219ee76807422991518..ac2fb09072264a6c3e02eb909ce6ab47cb3730b6 100644 (file)
@@ -3167,6 +3167,29 @@ A newline can have a @code{line-height} text or overlay property that
 controls the total height of the display line ending in that newline.
 @xref{Line Height}.
 
+@item wrap-prefix
+If text has a @code{wrap-prefix} property, the prefix it defines will
+be added at display-time to the beginning of every continuation line
+due to text wrapping (so if lines are truncated, the wrap-prefix is
+never used).  It may be a string, an image, or a stretch-glyph such as
+used by the @code{display} text-property.  @xref{Display Property}.
+
+A wrap-prefix may also be specified for an entire buffer using the
+@code{wrap-prefix} buffer-local variable (however, a
+@code{wrap-prefix} text-property takes precedence over the value of
+the @code{wrap-prefix} variable).  @xref{Truncation}.
+
+@item line-prefix
+If text has a @code{line-prefix} property, the prefix it defines will
+be added at display-time to the beginning of every non-continuation
+line.  It may be a string, an image, or a stretch-glyph such as used
+by the @code{display} text-property.  @xref{Display Property}.
+
+A line-prefix may also be specified for an entire buffer using the
+@code{line-prefix} buffer-local variable (however, a
+@code{line-prefix} text-property takes precedence over the value of
+the @code{line-prefix} variable).  @xref{Truncation}.
+
 @item modification-hooks
 @cindex change hooks for a character
 @cindex hooks for changing a character
index 78ee4596e9bac4d40e03cdb3107b8c28ba5d94af..3a4f08e00ccfe6e7a702c81796e35664a5d73f8e 100644 (file)
@@ -1,3 +1,20 @@
+2008-06-30  Miles Bader  <Miles Bader <miles@gnu.org>>
+
+       * dispextern.h (struct glyph, struct it, struct iterator_stack_entry):
+       Add `avoid_cursor_p' field.
+
+       * xdisp.c (push_it, pop_it): Save/restore avoid_cursor_p field.
+       (set_cursor_from_row): Skip glyphs with avoid_cursor_p set.
+       (append_glyph, append_composite_glyph, produce_image_glyph)
+       (append_stretch_glyph): Initialize avoid_cursor_p
+       (get_it_property): Renamed from `get_line_height_property'.
+       (x_produce_glyphs): Use get_it_property.
+       (handle_line_prefix, push_display_prop): New functions.
+       (display_line, move_it_in_display_line_to): Handle line/wrap prefixes.
+       (Vwrap_prefix, Qwrap_prefix, Vline_prefix, Qline_prefix): New
+       variables.
+       (syms_of_xdisp): Initialize them.
+
 2008-06-30  Kenichi Handa  <handa@m17n.org>
 
        * xftfont.c (xftfont_open): Don't call FcConfigSubstitute and
index 1761bede3e2e3e230e2387d8c28437320107e57b..041d54ffdc315ad11a39bb0afc859f4a256be26e 100644 (file)
@@ -366,7 +366,11 @@ struct glyph
      doesn't have a glyph in a font.  */
   unsigned glyph_not_available_p : 1;
 
-#define FACE_ID_BITS   21
+  /* Non-zero means don't display cursor here.  */
+  unsigned avoid_cursor_p : 1;
+
+#define FACE_ID_BITS   20
 
   /* Face of the glyph.  This is a realized face ID,
      an index in the face cache of the frame.  */
@@ -1887,6 +1891,9 @@ struct it
      this is 1 if we're doing an ellipsis.  Otherwise meaningless.  */
   unsigned ellipsis_p : 1;
 
+  /* True means cursor shouldn't be displayed here.  */
+  unsigned avoid_cursor_p : 1;
+
   /* Display table in effect or null for none.  */
   struct Lisp_Char_Table *dp;
 
@@ -1987,6 +1994,7 @@ struct it
     unsigned multibyte_p : 1;
     unsigned string_from_display_prop_p : 1;
     unsigned display_ellipsis_p : 1;
+    unsigned avoid_cursor_p : 1;
 
     /* properties from display property that are reset by another display property. */
     Lisp_Object space_width;
index 1527ba096d9802c3685ad2a81cc3d5be1d82b4dc..692db8b4999b4f86c61432a615390edf23cfcec3 100644 (file)
@@ -262,6 +262,9 @@ Lisp_Object Qfontification_functions;
    cursor moves into it.  */
 Lisp_Object Vmouse_autoselect_window;
 
+Lisp_Object Vwrap_prefix, Qwrap_prefix;
+Lisp_Object Vline_prefix, Qline_prefix;
+
 /* Non-zero means draw tool bar buttons raised when the mouse moves
    over them.  */
 
@@ -853,6 +856,10 @@ static int cursor_row_p P_ ((struct window *, struct glyph_row *));
 static int redisplay_mode_lines P_ ((Lisp_Object, int));
 static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
 
+static Lisp_Object get_it_property P_ ((struct it *it, Lisp_Object prop));
+
+static void handle_line_prefix P_ ((struct it *));
+
 #if 0
 static int invisible_text_between_p P_ ((struct it *, int, int));
 #endif
@@ -5210,6 +5217,7 @@ push_it (it)
   p->string_nchars = it->string_nchars;
   p->area = it->area;
   p->multibyte_p = it->multibyte_p;
+  p->avoid_cursor_p = it->avoid_cursor_p;
   p->space_width = it->space_width;
   p->font_height = it->font_height;
   p->voffset = it->voffset;
@@ -5271,6 +5279,7 @@ pop_it (it)
   it->string_nchars = p->string_nchars;
   it->area = p->area;
   it->multibyte_p = p->multibyte_p;
+  it->avoid_cursor_p = p->avoid_cursor_p;
   it->space_width = p->space_width;
   it->font_height = p->font_height;
   it->voffset = p->voffset;
@@ -6677,6 +6686,12 @@ move_it_in_display_line_to (struct it *it,
        || (it->method == GET_FROM_DISPLAY_VECTOR               \
           && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
 
+  /* If there's a line-/wrap-prefix, handle it.  */
+  if (it->hpos == 0 && it->method == GET_FROM_BUFFER
+      && it->current_y < it->last_visible_y)
+    {
+      handle_line_prefix (it);
+    }
 
   while (1)
     {
@@ -12222,7 +12237,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
   while (glyph < end
         && !INTEGERP (glyph->object)
         && (!BUFFERP (glyph->object)
-            || (last_pos = glyph->charpos) < pt_old))
+            || (last_pos = glyph->charpos) < pt_old
+            || glyph->avoid_cursor_p))
     {
       if (! STRINGP (glyph->object))
        {
@@ -16290,6 +16306,78 @@ cursor_row_p (w, row)
   return cursor_row_p;
 }
 
+\f
+
+/* Push the display property PROP so that it will be rendered at the
+   current position in IT.  */
+
+static void
+push_display_prop (struct it *it, Lisp_Object prop)
+{
+  push_it (it);
+
+  /* Never display a cursor on the prefix.  */
+  it->avoid_cursor_p = 1;
+
+  if (STRINGP (prop))
+    {
+      if (SCHARS (prop) == 0)
+       {
+         pop_it (it);
+         return;
+       }
+
+      it->string = prop;
+      it->multibyte_p = STRING_MULTIBYTE (it->string);
+      it->current.overlay_string_index = -1;
+      IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+      it->end_charpos = it->string_nchars = SCHARS (it->string);
+      it->method = GET_FROM_STRING;
+      it->stop_charpos = 0;
+    }
+  else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
+    {
+      it->method = GET_FROM_STRETCH;
+      it->object = prop;
+    }
+#ifdef HAVE_WINDOW_SYSTEM
+  else if (IMAGEP (prop))
+    {
+      it->what = IT_IMAGE;
+      it->image_id = lookup_image (it->f, prop);
+      it->method = GET_FROM_IMAGE;
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+  else
+    {
+      pop_it (it);             /* bogus display property, give up */
+      return;
+    }
+}
+
+/* See if there's a line- or wrap-prefix, and if so, push it on IT.  */
+
+static void
+handle_line_prefix (struct it *it)
+{
+  Lisp_Object prefix;
+  if (it->continuation_lines_width > 0)
+    {
+      prefix = get_it_property (it, Qwrap_prefix);
+      if (NILP (prefix))
+       prefix = Vwrap_prefix;
+    }
+  else
+    {
+      prefix = get_it_property (it, Qline_prefix);
+      if (NILP (prefix))
+       prefix = Vline_prefix;
+    }
+  if (! NILP (prefix))
+    push_display_prop (it, prefix);
+}
+
+\f
 
 /* Construct the glyph row IT->glyph_row in the desired matrix of
    IT->w from text at the current position of IT.  See dispextern.h
@@ -16348,6 +16436,13 @@ display_line (it)
       move_it_in_display_line_to (it, ZV, it->first_visible_x,
                                  MOVE_TO_POS | MOVE_TO_X);
     }
+  else
+    {
+      /* We only do this when not calling `move_it_in_display_line_to'
+        above, because move_it_in_display_line_to calls
+        handle_line_prefix itself.  */
+      handle_line_prefix (it);
+    }
 
   /* Get the initial row height.  This is either the height of the
      text hscrolled, if there is any, or zero.  */
@@ -20310,6 +20405,7 @@ append_glyph (it)
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = CHAR_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20348,6 +20444,7 @@ append_composite_glyph (it)
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = COMPOSITE_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20529,6 +20626,7 @@ produce_image_glyph (it)
          glyph->descent = it->descent;
          glyph->voffset = it->voffset;
          glyph->type = IMAGE_GLYPH;
+         glyph->avoid_cursor_p = it->avoid_cursor_p;
          glyph->multibyte_p = it->multibyte_p;
          glyph->left_box_line_p = it->start_of_box_run_p;
          glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20573,6 +20671,7 @@ append_stretch_glyph (it, object, width, height, ascent)
       glyph->descent = height - ascent;
       glyph->voffset = it->voffset;
       glyph->type = STRETCH_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20740,12 +20839,10 @@ produce_stretch_glyph (it)
   take_vertical_position_into_account (it);
 }
 
-/* Get line-height and line-spacing property at point.
-   If line-height has format (HEIGHT TOTAL), return TOTAL
-   in TOTAL_HEIGHT.  */
+/* Return the character-property PROP at the current position in IT.  */
 
 static Lisp_Object
-get_line_height_property (it, prop)
+get_it_property (it, prop)
      struct it *it;
      Lisp_Object prop;
 {
@@ -21048,7 +21145,7 @@ x_produce_glyphs (it)
          it->pixel_width = 0;
          it->nglyphs = 0;
 
-         height = get_line_height_property(it, Qline_height);
+         height = get_it_property(it, Qline_height);
          /* Split (line-height total-height) list */
          if (CONSP (height)
              && CONSP (XCDR (height))
@@ -21110,7 +21207,7 @@ x_produce_glyphs (it)
                spacing = calc_line_height_property(it, total_height, font, boff, 0);
              else
                {
-                 spacing = get_line_height_property(it, Qline_spacing);
+                 spacing = get_it_property(it, Qline_spacing);
                  spacing = calc_line_height_property(it, spacing, font, boff, 0);
                }
              if (INTEGERP (spacing))
@@ -24924,6 +25021,32 @@ The enable predicate for a menu binding should check this variable.  */);
     doc: /* Non-nil means don't update menu bars.  Internal use only.  */);
   inhibit_menubar_update = 0;
 
+  DEFVAR_LISP ("wrap-prefix", &Vwrap_prefix,
+    doc: /* Prefix added to the beginning of all continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `wrap-prefix' text-property.
+
+To add a prefix to non-continuation lines, use the `line-prefix' variable.  */);
+  Vwrap_prefix = Qnil;
+  staticpro (&Qwrap_prefix);
+  Qwrap_prefix = intern ("wrap-prefix");
+  Fmake_variable_buffer_local (Qwrap_prefix);
+
+  DEFVAR_LISP ("line-prefix", &Vline_prefix,
+    doc: /* Prefix added to the beginning of all non-continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `line-prefix' text-property.
+
+To add a prefix to continuation lines, use the `wrap-prefix' variable.  */);
+  Vline_prefix = Qnil;
+  staticpro (&Qline_prefix);
+  Qline_prefix = intern ("line-prefix");
+  Fmake_variable_buffer_local (Qline_prefix);
+
   DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
     doc: /* Non-nil means don't eval Lisp during redisplay.  */);
   inhibit_eval_during_redisplay = 0;