unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Stefan Monnier <monnier@iro.umontreal.ca>
To: 37858@debbugs.gnu.org
Subject: bug#37858: 27.0.50; Ensure a minimum width for `space` display prop
Date: Mon, 21 Oct 2019 16:03:58 -0400	[thread overview]
Message-ID: <jwvy2xdams1.fsf@iro.umontreal.ca> (raw)

Package: Emacs
Version: 27.0.50


For text displayed in columns, alignment is generally obtained with
a `display` text-property of the form

    (space :align-to FOO)

This works great when the previous text ends before FOO, but when we
mis-calculate (or didn't calculate at all) and the previous text already
extends further than the desired alignment of the following text, such
space is reduced down to 0 pixels which is often not what we want.

Sometimes one can workaround this by placing 2 spaces in the buffer: one
with the :align-to and another fixed size space.  But it can be
cumbersome to do that and it leads to undesirable artifacts (e.g. the
cursor can be placed between the two space).

So, I'd like to extend our `space` specifications so as to be able to
specify a minimum width.  I came up with the patch below which lets you
write:

    (space :align-to FOO :min-width BAR)

which seems to work fine, but while trying to update the Elisp doc for
it I realized that maybe a better option is to extend the acceptable
forms for FOO so it can be of the form:

    (space :align-to (max FOO (+ BAR current-x)))

WDYT?


        Stefan


diff --git a/src/xdisp.c b/src/xdisp.c
index be1c209553..fd825d2dfe 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -29218,6 +29218,28 @@ append_stretch_glyph (struct it *it, Lisp_Object object,
 
 #endif	/* HAVE_WINDOW_SYSTEM */
 
+static int
+compute_relative_width (struct it *it, Lisp_Object prop)
+{
+  struct it it2;
+  unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
+
+  it2 = *it;
+  if (it->multibyte_p)
+    it2.c = it2.char_to_display = STRING_CHAR_AND_LENGTH (p, it2.len);
+  else
+    {
+      it2.c = it2.char_to_display = *p, it2.len = 1;
+      if (! ASCII_CHAR_P (it2.c))
+	it2.char_to_display = BYTE8_TO_CHAR (it2.c);
+    }
+
+  it2.glyph_row = NULL;
+  it2.what = IT_CHARACTER;
+  PRODUCE_GLYPHS (&it2);
+  return NUMVAL (prop) * it2.pixel_width;
+}
+
 /* Produce a stretch glyph for iterator IT.  IT->object is the value
    of the glyph property displayed.  The value must be a list
    `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
@@ -29288,23 +29310,7 @@ produce_stretch_glyph (struct it *it)
       /* Relative width `:relative-width FACTOR' specified and valid.
 	 Compute the width of the characters having the `glyph'
 	 property.  */
-      struct it it2;
-      unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
-
-      it2 = *it;
-      if (it->multibyte_p)
-	it2.c = it2.char_to_display = STRING_CHAR_AND_LENGTH (p, it2.len);
-      else
-	{
-	  it2.c = it2.char_to_display = *p, it2.len = 1;
-	  if (! ASCII_CHAR_P (it2.c))
-	    it2.char_to_display = BYTE8_TO_CHAR (it2.c);
-	}
-
-      it2.glyph_row = NULL;
-      it2.what = IT_CHARACTER;
-      PRODUCE_GLYPHS (&it2);
-      width = NUMVAL (prop) * it2.pixel_width;
+      width = compute_relative_width (it, prop);
     }
   else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
 	   && calc_pixel_width_or_height (&tem, it, prop, font, true,
@@ -29323,6 +29329,21 @@ produce_stretch_glyph (struct it *it)
     /* Nothing specified -> width defaults to canonical char width.  */
     width = FRAME_COLUMN_WIDTH (it->f);
 
+  if ((prop = Fplist_get (plist, QCmin_width), !NILP (prop))
+      && calc_pixel_width_or_height (&tem, it, prop, font, true, 0))
+    {
+      /* Absolute minimum width `:min-width WIDTH' specified and valid.  */
+      if (width < tem)
+        width = tem;
+    }
+  else if (prop = Fplist_get (plist, QCmin_relative_width), NUMVAL (prop) > 0)
+    {
+      /* Relative width `:min-relative-width FACTOR' specified and valid.  */
+      int tem = compute_relative_width (it, prop);
+      if (width < tem)
+        width = tem;
+    }
+
   if (width <= 0 && (width < 0 || !zero_width_ok_p))
     width = 1;
 
@@ -34275,6 +34296,8 @@ syms_of_xdisp (void)
   DEFSYM (QCalign_to, ":align-to");
   DEFSYM (QCrelative_width, ":relative-width");
   DEFSYM (QCrelative_height, ":relative-height");
+  DEFSYM (QCmin_relative_width, ":min-relative-width");
+  DEFSYM (QCmin_width, ":min-width");
   DEFSYM (QCeval, ":eval");
   DEFSYM (QCpropertize, ":propertize");
   DEFSYM (QCfile, ":file");






             reply	other threads:[~2019-10-21 20:03 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-21 20:03 Stefan Monnier [this message]
2019-10-22  8:03 ` bug#37858: 27.0.50; Ensure a minimum width for `space` display prop Robert Pluim
2019-10-22 15:08 ` Eli Zaretskii
2022-05-07 12:07 ` bug#37880: 27.0.50; Changing font size in Info-mode messes up formatting Lars Ingebrigtsen
2022-05-07 14:29   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-05-07 14:38     ` bug#37858: " Eli Zaretskii
2022-05-07 15:58       ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-05-07 16:06         ` bug#37880: " Eli Zaretskii
2022-05-07 16:20           ` Eli Zaretskii

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=jwvy2xdams1.fsf@iro.umontreal.ca \
    --to=monnier@iro.umontreal.ca \
    --cc=37858@debbugs.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).