unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* line/wrap-prefix patch
@ 2008-06-30  3:38 Miles Bader
  2008-06-30  4:18 ` Miles Bader
  2008-07-01 22:19 ` Stephen Berman
  0 siblings, 2 replies; 13+ messages in thread
From: Miles Bader @ 2008-06-30  3:38 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 879 bytes --]

Here's a patch that implements the "wrap-prefix" feature discussed
earlier.  It allows a prefix to be added to the beginning of each line
wrapped by redisplay.  It works with both word-wrapping and non-word
wrapping.

I also added a "line-prefix" feature which is the same thing for _non_
wrapped lines.

There are both buffer-local variables (`line-prefix', `wrap-prefix') and
text-property/overlay versions of both.

They may contain a string, an image or a `display'-property style
"space" spec.

Besides my current usage (adding "hanging indents" to word-wrapped-lines
in rcirc buffers), these features could be used to add other sorts of
word-processor-style spacing frobs, such as an implicit paragraph indent
(using line-prefix), additional vertical whitespace between "paragraphs"
(using a line-prefix with a value like (space :height 1.5)), etc.

Any comments?

-Miles


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: line/wrap-prefix patch --]
[-- Type: text/x-patch, Size: 10005 bytes --]

orig = emacs@sv.gnu.org/emacs--devo--0--patch-1298
mod = emacs@sv.gnu.org/emacs--devo--0--patch-1298

M  src/dispextern.h
M  src/ChangeLog
M  src/xdisp.c

--- orig/src/ChangeLog
+++ mod/src/ChangeLog
@@ -1,3 +1,19 @@
+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  Chong Yidong  <cyd@stupidchicken.com>
 
 	* xfaces.c (Finternal_merge_in_global_face): If default face was


--- orig/src/dispextern.h
+++ mod/src/dispextern.h
@@ -366,7 +366,11 @@
      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 @@
      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 @@
     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;


--- orig/src/xdisp.c
+++ mod/src/xdisp.c
@@ -262,6 +262,9 @@
    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 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 @@
   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 @@
   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 @@
        || (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 @@
   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 @@
   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 @@
       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 @@
       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 @@
       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 @@
 	  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 @@
       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 @@
   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 @@
 	  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 @@
 		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 @@
     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;




[-- Attachment #3: Type: text/plain, Size: 66 bytes --]



-- 
Success, n. The one unpardonable sin against one's fellows.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2008-07-06  1:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-30  3:38 line/wrap-prefix patch Miles Bader
2008-06-30  4:18 ` Miles Bader
2008-07-01  0:36   ` Miles Bader
2008-07-01  4:52     ` Chong Yidong
2008-07-01  5:38       ` Miles Bader
2008-07-01 14:10         ` Chong Yidong
2008-07-01 22:19 ` Stephen Berman
2008-07-03  4:19   ` Miles Bader
2008-07-04 20:50     ` Stephen Berman
2008-07-04 21:25       ` Stefan Monnier
2008-07-05  0:52       ` Miles Bader
2008-07-05 21:30         ` Stephen Berman
2008-07-06  1:05           ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).