From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Miles Bader Newsgroups: gmane.emacs.devel Subject: line/wrap-prefix patch Date: Sun, 29 Jun 2008 23:38:02 -0400 Message-ID: <61zlp3k2xx.fsf@fencepost.gnu.org> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1214797112 21054 80.91.229.12 (30 Jun 2008 03:38:32 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 30 Jun 2008 03:38:32 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Jun 30 05:39:17 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1KDAET-0004Y2-Uc for ged-emacs-devel@m.gmane.org; Mon, 30 Jun 2008 05:39:14 +0200 Original-Received: from localhost ([127.0.0.1]:51888 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KDADd-0006ws-EF for ged-emacs-devel@m.gmane.org; Sun, 29 Jun 2008 23:38:21 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KDADZ-0006wd-Cl for emacs-devel@gnu.org; Sun, 29 Jun 2008 23:38:17 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KDADY-0006wR-UE for emacs-devel@gnu.org; Sun, 29 Jun 2008 23:38:17 -0400 Original-Received: from [199.232.76.173] (port=36901 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KDADY-0006wK-JA for emacs-devel@gnu.org; Sun, 29 Jun 2008 23:38:16 -0400 Original-Received: from fencepost.gnu.org ([140.186.70.10]:40999) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KDADY-0004D6-E2 for emacs-devel@gnu.org; Sun, 29 Jun 2008 23:38:16 -0400 Original-Received: from miles by fencepost.gnu.org with local (Exim 4.67) (envelope-from ) id 1KDADK-0007Vo-7r; Sun, 29 Jun 2008 23:38:02 -0400 System-Type: x86_64-unknown-linux-gnu Blat: Foop X-detected-kernel: by monty-python.gnu.org: Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:100184 Archived-At: --=-=-= 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 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=wrap-prefix-20080630-3.patch Content-Description: line/wrap-prefix patch 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 > + + * 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 * 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; } + + +/* 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); +} + + /* 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; --=-=-= -- Success, n. The one unpardonable sin against one's fellows. --=-=-=--