--- /dev/null
+;;; display-fill-column-indicator.el --- interface for display-fill-column-indicator -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017-2019 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+;; Keywords: convenience
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Provides a minor mode interface for `display-fill-column-indicator'.
+;;
+;; Toggle display of line numbers with M-x
+;; display-fill-column-indicator-mode. To enable line numbering in
+;; all buffers, use M-x global-display-fill-column-indicator-mode. To
+;; change the default line column
+
+
+;; NOTE: Customization variables for
+;; `display-fill-column-indicator-column' and
+;; `display-fill-column-indicator-char' itself are defined in
+;; cus-start.el.
+
+;;; Code:
+
+(defgroup display-fill-column-indicator nil
+ "Display line numbers in the buffer."
+ :group 'convenience
+ :group 'display)
+
+
+;;;###autoload
+(define-minor-mode display-fill-column-indicator-mode
+ "Toggle display fill column indicator.
+This uses `display-fill-column-indicator' internally.
+
+To change the position of the line displayed by default,
+customize `display-fill-column-indicator-column' you can change the
+character for the line setting `display-fill-column-indicator-character'."
+ :lighter nil
+ (if display-fill-column-indicator-mode
+ (progn
+ (setq display-fill-column-indicator t)
+ (unless display-fill-column-indicator-column
+ (setq display-fill-column-indicator-column fill-column))
+ (unless display-fill-column-indicator-character
+ (if (char-displayable-p ?\u2502)
+ (setq display-fill-column-indicator-character ?\u2502)
+ (setq display-fill-column-indicator-character ?|))))
+ (setq display-fill-column-indicator nil)))
+
+(defun display-fill-column-indicator--turn-on ()
+ "Turn on `display-fill-column-indicator-mode'."
+ (unless (or (minibufferp)
+ (and (daemonp) (null (frame-parameter nil 'client))))
+ (display-fill-column-indicator-mode)))
+
+;;;###autoload
+(define-globalized-minor-mode global-display-fill-column-indicator-mode
+ display-fill-column-indicator-mode display-fill-column-indicator--turn-on)
+
+(provide 'display-fill-column-indicator)
+
+;;; display-fill-column-indicator.el ends here
it->what = IT_CHARACTER;
memset (&it->position, 0, sizeof it->position);
it->object = Qnil;
- it->c = it->char_to_display = ' ';
it->len = 1;
+ int local_default_face_id =
+ lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
+ struct face* default_face =
+ FACE_FROM_ID_OR_NULL (it->f, local_default_face_id);
+
+ /* Corner case for when display-fill-column-indicator-mode
+ is active and the extra character should be added in the
+ same place than the line */
+ if (!NILP (Vdisplay_fill_column_indicator)
+ && (it->w->pseudo_window_p == 0)
+ && FIXNATP (Vdisplay_fill_column_indicator_column)
+ && FIXNATP (Vdisplay_fill_column_indicator_character))
+ {
+ struct font *font =
+ default_face->font ? default_face->font : FRAME_FONT (it->f);
+ const int char_width =
+ font->average_width ? font->average_width : font->space_width;
+ const int fill_column =
+ XFIXNAT (Vdisplay_fill_column_indicator_column);
+ const int column_x =
+ char_width * fill_column + it->lnum_pixel_width;
+
+ if (it->current_x == column_x)
+ {
+ it->c = it->char_to_display =
+ XFIXNAT (Vdisplay_fill_column_indicator_character);
+ it->face_id =
+ merge_faces (it->w, Qfill_column_face, 0, DEFAULT_FACE_ID);
+ face = FACE_FROM_ID(it->f, it->face_id);
+ goto produce_glyphs;
+ }
+ }
+
+ it->c = it->char_to_display = ' ';
/* If the default face was remapped, be sure to use the
remapped face for the appended newline. */
if (default_face_p)
- it->face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
+ it->face_id = local_default_face_id;
else if (it->face_before_selective_p)
it->face_id = it->saved_face_id;
+
face = FACE_FROM_ID (it->f, it->face_id);
it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
/* In R2L rows, we will prepend a stretch glyph that will
set. */
if (it->glyph_row->reversed_p
/* But if the appended newline glyph goes all the way to
- the end of the row, there will be no stretch glyph,
- so leave the box flag set. */
+ the end of the row, there will be no stretch glyph,
+ so leave the box flag set. */
&& saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x)
it->end_of_box_run_p = false;
+ produce_glyphs:
PRODUCE_GLYPHS (it);
#ifdef HAVE_WINDOW_SYSTEM
#ifdef HAVE_WINDOW_SYSTEM
&& !face->stipple
#endif
- && !it->glyph_row->reversed_p)
+ && !it->glyph_row->reversed_p
+ && NILP (Vdisplay_fill_column_indicator))
return;
/* Set the glyph row flag indicating that the face of the last glyph
default_face->id;
it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
}
+
+ /* Display fill column indicator if not in modeline or
+ toolbar and display fill column indicator mode is
+ active */
+ if (!NILP (Vdisplay_fill_column_indicator)
+ && (it->w->pseudo_window_p == 0)
+ && FIXNATP (Vdisplay_fill_column_indicator_column)
+ && FIXNATP (Vdisplay_fill_column_indicator_character))
+ {
+ struct font *font =
+ default_face->font ? default_face->font : FRAME_FONT (f);
+ const int char_width =
+ font->average_width ? font->average_width : font->space_width;
+
+ const int fill_column =
+ XFIXNAT (Vdisplay_fill_column_indicator_column);
+
+ const int column_x = char_width * fill_column + it->lnum_pixel_width;
+
+ if ((it->current_x <= column_x)
+ && (column_x <= it->last_visible_x))
+ {
+ const char saved_char = it->char_to_display;
+ const struct text_pos saved_pos = it->position;
+ const bool saved_avoid_cursor = it->avoid_cursor_p;
+ const int saved_face_id = it->face_id;
+ const bool saved_box_start = it->start_of_box_run_p;
+ Lisp_Object save_object = it->object;
+
+ /* The stretch width needs to considet the latter added glyph */
+ const int stretch_width = column_x - it->current_x - char_width;
+
+ memset (&it->position, 0, sizeof it->position);
+ it->avoid_cursor_p = true;
+ it->object = Qnil;
+
+ /* Only generate a stretch glysph if there is distance between
+ current_x and and the indicator position */
+ if (stretch_width > 0)
+ {
+ int stretch_ascent = (((it->ascent + it->descent)
+ * FONT_BASE (font)) / FONT_HEIGHT (font));
+ append_stretch_glyph (it, Qnil, stretch_width,
+ it->ascent + it->descent, stretch_ascent);
+ }
+
+ /* Generate the glysph indicator only if append_space_for_newline
+ didn't already. */
+ if (it->current_x < column_x)
+ {
+ it->char_to_display =
+ XFIXNAT (Vdisplay_fill_column_indicator_character);
+ it->face_id =
+ merge_faces (it->w, Qfill_column_face, 0, DEFAULT_FACE_ID);
+ PRODUCE_GLYPHS (it);
+ }
+
+ /* Restore the face after the indicator was generated */
+ it->face_id = saved_face_id;
+
+ /* If there is space after the indicator generate an extra
+ empty glysph to restore the face. */
+ it->char_to_display = ' ';
+ PRODUCE_GLYPHS (it);
+
+ it->char_to_display = saved_char;
+ it->position = saved_pos;
+ it->avoid_cursor_p = saved_avoid_cursor;
+ it->start_of_box_run_p = saved_box_start;
+ it->object = save_object;
+ }
+ }
}
#ifdef HAVE_WINDOW_SYSTEM
+
if (it->glyph_row->reversed_p)
{
/* Prepend a stretch glyph to the row, such that the
it->face_id = default_face->id;
else
it->face_id = face->id;
- PRODUCE_GLYPHS (it);
- while (it->current_x <= it->last_visible_x)
- PRODUCE_GLYPHS (it);
+ /* Display fill-column-line if mode is active */
+ if (!NILP (Vdisplay_fill_column_indicator))
+ {
+ const int fill_column_indicator_line =
+ XFIXNAT (Vdisplay_fill_column_indicator_column)
+ + it->lnum_pixel_width;
+ do
+ {
+ if (it->current_x == fill_column_indicator_line)
+ {
+ const int saved_face = it->face_id;
+ it->face_id =
+ merge_faces (it->w, Qfill_column_face, 0, DEFAULT_FACE_ID);
+ it->c = it->char_to_display =
+ XFIXNAT (Vdisplay_fill_column_indicator_character);
+ PRODUCE_GLYPHS (it);
+ it->face_id = saved_face;
+ it->c = it->char_to_display = ' ';
+ }
+ else
+ PRODUCE_GLYPHS (it);
+ } while (it->current_x <= it->last_visible_x);
+ }
+ else
+ {
+ do
+ {
+ PRODUCE_GLYPHS (it);
+ } while (it->current_x <= it->last_visible_x);
+ }
if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
&& (it->glyph_row->used[RIGHT_MARGIN_AREA]
if (!row->reversed_p)
{
while (glyph >= start
- && glyph->type == CHAR_GLYPH
+ && (glyph->type == CHAR_GLYPH
+ || glyph->type == STRETCH_GLYPH)
&& NILP (glyph->object))
--glyph;
}
/* Name of a text property which disables line-number display. */
DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
+ /* Names of the face used to display fill column indicator character. */
+ DEFSYM (Qfill_column_face, "fill-column-face");
+
/* Name and number of the face used to highlight escape glyphs. */
DEFSYM (Qescape_glyph, "escape-glyph");
DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
+ DEFVAR_LISP ("display-fill-column-indicator", Vdisplay_fill_column_indicator,
+ doc: /* Non-nil means display the fill column indicator. */);
+ Vdisplay_fill_column_indicator = Qnil;
+ DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
+ Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
+
+ DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
+ doc: /* Column to draw the indicator when `display-fill-column-indicator' is non-nil.
+The default value is the variable `fill-column' if not other value is given. */);
+ Vdisplay_fill_column_indicator_column = Qnil;
+ DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
+ Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
+
+ DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
+ doc: /* Character to draw the indicator when `display-fill-column-indicator' is non-nil.
+The default is U+2502 but a good alternative is (ascii 124) if
+the font in fill-column-face does not support Unicode characters. */);
+ Vdisplay_fill_column_indicator_character = Qnil;
+ DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
+ Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
+
DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
doc: /* Non-nil means don't eval Lisp during redisplay. */);
inhibit_eval_during_redisplay = false;