From 1302c040a23837b80a53416421914f3fe8ba1926 Mon Sep 17 00:00:00 2001
From: Sungbin Jo <pcr910303@icloud.com>
Date: Fri, 24 Jan 2020 00:56:38 +0900
Subject: [PATCH] Add new variable for centering lines vertically.

Co-authored-by: Jesse Nazario <jessenzr@gmail.com>

When using line-spacing, the new variable line-spacing-vertical-center
can be set to non-nil to center the line content vertically.

* src/buffer.h (struct buffer): New member line_spacing_vertical_center.
* src/buffer.c (bset_line_spacing_vertical_center): New setter for
line_spacing_vertical_center.
(reset_buffer): Reset line_spacing_vertical_center.
(init_buffer_once): Initialize line_spacing_vertical_center.
(syms_of_buffer): Declare Lisp variable line-spacing-vertical-center.
* src/xdisp.c (gui_produce_glyphs): Center the text when
line-spacing-vertical-center is non-nil.
* doc/lispref/display.texi (Line Height): Document the new variable.
* etc/NEWS: Announce the new variable.
---
 doc/lispref/display.texi |  5 +++++
 etc/NEWS                 |  4 ++++
 src/buffer.c             | 14 ++++++++++++++
 src/buffer.h             |  4 ++++
 src/xdisp.c              | 10 +++++++++-
 5 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index e4980fe4c3..2fa63ddb56 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -2231,6 +2231,11 @@ Line Height
 number of pixels put below lines.  A floating-point number specifies
 the spacing relative to the frame's default line height.
 
+  The @code{line-spacing} parameter creates the space by putting some
+margin only below the line.  If you wish to center the line vertically
+instead, you can set the variable @code{line-spacing-vertical-center}
+as non-nil.
+
 @vindex line-spacing
   You can specify the line spacing for all lines in a buffer via the
 buffer-local @code{line-spacing} variable.  An integer specifies
diff --git a/etc/NEWS b/etc/NEWS
index 11ef31b2c8..fb85131f07 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -51,6 +51,10 @@ It was declared obsolete in Emacs 27.1.
 
 * Changes in Emacs 28.1
 
+** New variable line-spacing-vertical-center.
+This variable, if non-nil, centers the line content vertically when
+using the 'line-spacing' variable.
+
 
 * Editing Changes in Emacs 28.1
 
diff --git a/src/buffer.c b/src/buffer.c
index 5c65d4d4d1..234745a66a 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -219,6 +219,11 @@ bset_extra_line_spacing (struct buffer *b, Lisp_Object val)
   b->extra_line_spacing_ = val;
 }
 static void
+bset_line_spacing_vertical_center (struct buffer *b, Lisp_Object val)
+{
+  b->line_spacing_vertical_center_ = val;
+}
+static void
 bset_file_format (struct buffer *b, Lisp_Object val)
 {
   b->file_format_ = val;
@@ -967,6 +972,8 @@ reset_buffer (register struct buffer *b)
     (b, BVAR (&buffer_defaults, enable_multibyte_characters));
   bset_cursor_type (b, BVAR (&buffer_defaults, cursor_type));
   bset_extra_line_spacing (b, BVAR (&buffer_defaults, extra_line_spacing));
+  bset_line_spacing_vertical_center (b, BVAR (&buffer_defaults,
+                                              line_spacing_vertical_center));
 
   b->display_error_modiff = 0;
 }
@@ -5202,6 +5209,7 @@ init_buffer_once (void)
   XSETFASTINT (BVAR (&buffer_local_flags, tab_line_format), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, cursor_type), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, extra_line_spacing), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, line_spacing_vertical_center), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, cursor_in_non_selected_windows), idx); ++idx;
 
   /* buffer_local_flags contains no pointers, so it's safe to treat it
@@ -5272,6 +5280,7 @@ init_buffer_once (void)
   bset_bidi_paragraph_separate_re (&buffer_defaults, Qnil);
   bset_cursor_type (&buffer_defaults, Qt);
   bset_extra_line_spacing (&buffer_defaults, Qnil);
+  bset_line_spacing_vertical_center (&buffer_defaults, Qnil);
   bset_cursor_in_non_selected_windows (&buffer_defaults, Qt);
 
   bset_enable_multibyte_characters (&buffer_defaults, Qt);
@@ -6268,6 +6277,11 @@ from (abs POSITION).  If POSITION is positive, point was at the front
 If value is a floating point number, it specifies the spacing relative
 to the default frame line height.  A value of nil means add no extra space.  */);
 
+  DEFVAR_PER_BUFFER ("line-spacing-vertical-center",
+		     &BVAR (current_buffer, line_spacing_vertical_center), Qnil,
+                     doc: /* Non-nil means center the line content vertically
+when using `line-spacing' variable.  */);
+
   DEFVAR_PER_BUFFER ("cursor-in-non-selected-windows",
 		     &BVAR (current_buffer, cursor_in_non_selected_windows), Qnil,
 		     doc: /* Non-nil means show a cursor in non-selected windows.
diff --git a/src/buffer.h b/src/buffer.h
index fd05fdd37d..c15065b599 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -553,6 +553,10 @@ #define BVAR(buf, field) ((buf)->field ## _)
      in the display of this buffer.  */
   Lisp_Object extra_line_spacing_;
 
+  /* Non-nil means center the line content vertically. To be used
+     along with `line-spacing'.  */
+  Lisp_Object line_spacing_vertical_center_;
+
   /* Cursor type to display in non-selected windows.
      t means to use hollow box cursor.
      See `cursor-type' for other values.  */
diff --git a/src/xdisp.c b/src/xdisp.c
index a5efbb39be..44727cdd64 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -30527,7 +30527,15 @@ gui_produce_glyphs (struct it *it)
 
   if (extra_line_spacing > 0)
     {
-      it->descent += extra_line_spacing;
+      if (NILP (BVAR (XBUFFER (it->w->contents),
+                      line_spacing_vertical_center)))
+        it->descent += extra_line_spacing;
+      else
+        {
+          int spacing = extra_line_spacing / 2;
+          it->ascent += spacing;
+          it->descent += spacing;
+        }
       if (extra_line_spacing > it->max_extra_line_spacing)
 	it->max_extra_line_spacing = extra_line_spacing;
     }
-- 
2.21.1 (Apple Git-122.3)

