From: Miles Bader <miles@gnu.org>
To: emacs-devel@gnu.org
Subject: line/wrap-prefix patch
Date: Sun, 29 Jun 2008 23:38:02 -0400 [thread overview]
Message-ID: <61zlp3k2xx.fsf@fencepost.gnu.org> (raw)
[-- 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.
next reply other threads:[~2008-06-30 3:38 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-30 3:38 Miles Bader [this message]
2008-06-30 4:18 ` line/wrap-prefix patch 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=61zlp3k2xx.fsf@fencepost.gnu.org \
--to=miles@gnu.org \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).