unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
@ 2012-11-27 10:42 mario giovinazzo
  2012-11-27 17:43 ` Eli Zaretskii
                   ` (2 more replies)
  0 siblings, 3 replies; 28+ messages in thread
From: mario giovinazzo @ 2012-11-27 10:42 UTC (permalink / raw)
  To: 13011

*** E-Mail body has been placed on clipboard, please paste it here! ***

The problem occurs when I customize hl-line enabling box around text
to make evident the current line.
The box around text (also 1 pixel) changes the inside text position
thus producing a vertical and horizontal flickering when I move the cursor.
Setting a box of width -1 (a negative number) stops the vertical
flickering but still remains the horizontal one.





In GNU Emacs 24.2.1 (i386-mingw-nt5.1.2600)
 of 2012-08-29 on MARVIN
Windowing system distributor `Microsoft Corp.', version 5.1.2600
Configured using:
 `configure --with-gcc (4.6) --cflags
 -ID:/devel/emacs/libs/libXpm-3.5.8/include
 -ID:/devel/emacs/libs/libXpm-3.5.8/src
 -ID:/devel/emacs/libs/libpng-dev_1.4.3-1/include
 -ID:/devel/emacs/libs/zlib-dev_1.2.5-2/include
 -ID:/devel/emacs/libs/giflib-4.1.4-1/include
 -ID:/devel/emacs/libs/jpeg-6b-4/include
 -ID:/devel/emacs/libs/tiff-3.8.2-1/include
 -ID:/devel/emacs/libs/gnutls-3.0.9/include'

Important settings:
  value of $LC_ALL: nil
  value of $LC_COLLATE: nil
  value of $LC_CTYPE: nil
  value of $LC_MESSAGES: nil
  value of $LC_MONETARY: nil
  value of $LC_NUMERIC: nil
  value of $LC_TIME: nil
  value of $LANG: ENG
  value of $XMODIFIERS: nil
  locale-coding-system: cp1252
  default enable-multibyte-characters: t

Major mode: Lisp Interaction

Minor modes in effect:
  show-paren-mode: t
  global-hl-line-mode: t
  global-hi-lock-mode: t
  hi-lock-mode: t
  cua-mode: t
  tooltip-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  size-indication-mode: t
  column-number-mode: t
  line-number-mode: t
  global-visual-line-mode: t
  visual-line-mode: t
  transient-mark-mode: t

Recent input:
<help-echo> <help-echo> <help-echo> <help-echo> <help-echo> 
<help-echo> <tool-bar> <kill-buffer> <help-echo> <help-echo> 
M-x C-y <return>

Recent messages:
Loading cua-base...done
Loading delsel...done
Loading hi-lock...done
Loading hl-line...done
Loading paren...done
For information about GNU Emacs and the GNU system, type C-h C-a.
.emacs has auto save data; consider M-x recover-this-file

Load-path shadows:
None found.

Features:
(shadow sort gnus-util mail-extr emacsbug message format-spec rfc822 mml
easymenu mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231
mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums
mm-util mail-prsvr mail-utils time windmove cc-styles cc-align cc-engine
cc-vars cc-defs regexp-opt tempo-c-cpp tempo edmacro kmacro uniquify
advice help-fns advice-preload paren hl-line hi-lock delsel cua-base
cus-start cus-load time-date tooltip ediff-hook vc-hooks lisp-float-type
mwheel dos-w32 disp-table ls-lisp w32-win w32-vars tool-bar dnd fontset
image fringe lisp-mode register page menu-bar rfn-eshadow timer select
scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame cham
georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese hebrew greek romanian slovak czech european ethiopic
indian cyrillic chinese case-table epa-hook jka-cmpr-hook help simple
abbrev minibuffer loaddefs button faces cus-face files text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote make-network-process multi-tty emacs)






^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-11-27 10:42 bug#13011: 24.2; Text flickering moving cursor with box around text enabled mario giovinazzo
@ 2012-11-27 17:43 ` Eli Zaretskii
       [not found]   ` <1205106717.20121128161453@virgilio.it>
  2018-01-19 18:08 ` bug#13011: Patch: " Alexandre Adolphe
  2019-08-10 21:21 ` bug#13011: [PATCH] " Alexandre Adolphe
  2 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2012-11-27 17:43 UTC (permalink / raw)
  To: mario giovinazzo; +Cc: 13011

> Date: Tue, 27 Nov 2012 11:42:24 +0100
> From: mario giovinazzo <mario.giovinazzo@virgilio.it>
> 
> The problem occurs when I customize hl-line enabling box around text
> to make evident the current line.
> The box around text (also 1 pixel) changes the inside text position
> thus producing a vertical and horizontal flickering when I move the cursor.
> Setting a box of width -1 (a negative number) stops the vertical
> flickering but still remains the horizontal one.

Can you please show a minimal recipe to reproduce this starting with
"emacs -Q"?  That will make the job of looking into this much easier.

Thanks.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
       [not found]   ` <1205106717.20121128161453@virgilio.it>
@ 2012-11-28 17:54     ` Eli Zaretskii
  2012-11-29  4:39       ` Stefan Monnier
  0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2012-11-28 17:54 UTC (permalink / raw)
  To: mario giovinazzo; +Cc: 13011

[Please keep the bug address on the CC list.]

> Date: Wed, 28 Nov 2012 16:14:53 +0100
> From: mario giovinazzo <mario.giovinazzo@virgilio.it>
> 
> To reproduce the behavior is very easy.
> My .emacs file contains only this 2  lines:
> 
> 
> (custom-set-variables '(global-hl-line-mode t))
> (custom-set-faces '(hl-line ((t (:box (:line-width 1 :color "gray50"))))))

Thanks.

> If you open any text file and move the cursor inside text with arrow key
> (up, down, right, left), the" box around text" follow the cursor,
> and the text flickers (I suppose +- 2 pixels). It is evident.

I see no flickering when moving cursor horizontally within the same
screen line.  None at all.

When moving cursor vertically, I see this:

  . The text of the current line moves slightly up when the current
    line moves up or down.

  . When the current line is empty, the text in all the lines below it
    moves up slightly, then moves back down when the current lines
    becomes a line with some text.

Is this what you call "flicker"?  Or do you see something else?

If the above is what you see, then please tell what you expect Emacs
to do instead.  You've changed the face of the current line such that
it takes slightly more pixels on the screen.  Emacs just obeys your
specifications, it cannot display a line in less pixels than it needs
to draw all of the characters on it in the face you requested.  The
same would happen if you set the hl-line face to use a larger font,
for example.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-11-28 17:54     ` Eli Zaretskii
@ 2012-11-29  4:39       ` Stefan Monnier
  2012-11-29 16:42         ` Eli Zaretskii
  0 siblings, 1 reply; 28+ messages in thread
From: Stefan Monnier @ 2012-11-29  4:39 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 13011, mario giovinazzo

>> (custom-set-variables '(global-hl-line-mode t))
>> (custom-set-faces '(hl-line ((t (:box (:line-width 1 :color "gray50"))))))
> Thanks.

Actually the interesting case is when the box is of width -1.

> I see no flickering when moving cursor horizontally within the same
> screen line.  None at all.

The problem is when moving vertically.

> If the above is what you see, then please tell what you expect Emacs
> to do instead.

When the box width is 1, indeed, there's no much Emacs could do, but
when the width is -1 (i.e. drawn "inside" the normal text box),
characters shouldn't move, whereas they do (they get shifted
horizontally by a few pixels, and if you try it in the *Help* buffer
you may see that the number of pixel shifts seems to increase at
transition points between different fonts, such as italics for function
arguments).


        Stefan





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-11-29  4:39       ` Stefan Monnier
@ 2012-11-29 16:42         ` Eli Zaretskii
  2012-11-29 19:06           ` Stefan Monnier
  0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2012-11-29 16:42 UTC (permalink / raw)
  To: Stefan Monnier, Kenichi Handa; +Cc: 13011, mario.giovinazzo

> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Cc: mario giovinazzo <mario.giovinazzo@virgilio.it>,  13011@debbugs.gnu.org
> Date: Wed, 28 Nov 2012 23:39:04 -0500
> 
> When the box width is 1, indeed, there's no much Emacs could do, but
> when the width is -1 (i.e. drawn "inside" the normal text box),
> characters shouldn't move, whereas they do (they get shifted
> horizontally by a few pixels, and if you try it in the *Help* buffer
> you may see that the number of pixel shifts seems to increase at
> transition points between different fonts, such as italics for function
> arguments).

Looks like this was done on (some) purpose:

In xdisp.c:

	  /* If face has a box, add the box thickness to the character
	     height.  If character has a box line to the left and/or
	     right, add the box line width to the character's width.  */
	  if (face->box != FACE_NO_BOX)
	    {
	      int thick = face->box_line_width;

	      if (thick > 0)
		{
		  it->ascent += thick;
		  it->descent += thick;
		}
	      else
		thick = -thick;   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

	      if (it->start_of_box_run_p)
		it->pixel_width += thick;  <<<<<<<<<<<<<<<<<<<<<<<<<
	      if (it->end_of_box_run_p)
		it->pixel_width += thick;
	    }

Note that the ascent and descent are only enlarged when the value is
positive, but pixel_width is also enlarged when the value is negative.

And then in xterm.c:

  /* If first glyph of S has a left box line, start drawing the text
     of S to the right of that box line.  */
  if (s->face->box != FACE_NO_BOX
      && s->first_glyph->left_box_line_p)
    x = s->x + eabs (s->face->box_line_width);  <<<<<<<<<<<<<<<<<<<<
  else         ^^^^
    x = s->x;

Moreover, the commentary in dispextern.h explicitly says that the
left/right borders are not affected by the sign of the box width (note
the last sentence):

  /* Non-zero means characters in this face have a box of that
     thickness around them.  If this value is negative, its absolute
     value indicates the thickness, and the horizontal (top and
     bottom) borders of box are drawn inside of the character glyphs'
     area.  The vertical (left and right) borders of the box are drawn
     in the same way as when this value is positive.  */
  int box_line_width;

and the doc string in faces.el only mentions the top and bottom borders
of the box as being affected by negative values:

  `:box'

  VALUE specifies whether characters in FACE should have a box drawn
  around them.  If VALUE is nil, explicitly don't draw boxes.  If
  VALUE is t, draw a box with lines of width 1 in the foreground color
  of the face.  If VALUE is a string, the string must be a color name,
  and the box is drawn in that color with a line width of 1.  Otherwise,
  VALUE must be a property list of the form `(:line-width WIDTH
  :color COLOR :style STYLE)'.  If a keyword/value pair is missing from
  the property list, a default value will be used for the value, as
  specified below.  WIDTH specifies the width of the lines to draw; it
  defaults to 1.  If WIDTH is negative, the absolute value is the width
  of the lines, and draw top/bottom lines inside the characters area,
  not around it.

Only the ELisp manual makes it sound like both horizontal and vertical
borders are drawn inside the character cell:

    `(:line-width WIDTH :color COLOR :style STYLE)'
          This way you can explicitly specify all aspects of the box.
          The value WIDTH specifies the width of the lines to draw; it
          defaults to 1.  A negative width -N means to draw a line of
          width N that occupies the space of the underlying text, thus
          avoiding any increase in the character height or width.

I made a provisional change that behaves with left and right borders
like it does with horizontal ones, and it seems to work, at least with
character display (didn't text with images, image slices, composite
characters, etc.).  But I'd like to ask Handa-san (CC'ed), who wrote
the code for this feature (almost 12 years ago!), whether he might
remember why the code deliberately makes the left and right borders
behave differently from top and bottom ones.

To see the original changeset that introduced this feature, type

   bzr diff -r 36005..36010





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-11-29 16:42         ` Eli Zaretskii
@ 2012-11-29 19:06           ` Stefan Monnier
  2012-12-03  9:29             ` Kenichi Handa
  0 siblings, 1 reply; 28+ messages in thread
From: Stefan Monnier @ 2012-11-29 19:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 13011, mario.giovinazzo

>      area.  The vertical (left and right) borders of the box are drawn
>      in the same way as when this value is positive.  */
>   int box_line_width;
[...]
> I made a provisional change that behaves with left and right borders
> like it does with horizontal ones, and it seems to work, at least with
> character display (didn't text with images, image slices, composite
> characters, etc.).  But I'd like to ask Handa-san (CC'ed), who wrote
> the code for this feature (almost 12 years ago!), whether he might
> remember why the code deliberately makes the left and right borders
> behave differently from top and bottom ones.

I'm curious as well.  The only think that comes to mind is that in most
fonts, there's usually some empty pixel-line(s) at the top and the
bottom, whereas there often't isn't any empty pixel-lines at all on the
left (and/or on the right) side.  So there's more risk of overwriting
useful pixels on the left&right than at top&bottom.


        Stefan





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
       [not found] <13b4ec68081.mario.giovinazzo@virgilio.it>
@ 2012-11-30  8:13 ` Eli Zaretskii
  2012-12-11 12:26   ` Eli Zaretskii
  0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2012-11-30  8:13 UTC (permalink / raw)
  To: mario.giovinazzo@virgilio.it; +Cc: 13011


[Please don't remove the bug address from the CC list, we want all
this discussion to be archived in the bug tracker.]

> Date: Fri, 30 Nov 2012 01:45:30 +0100 (CET)
> From: "mario.giovinazzo@virgilio.it" <mario.giovinazzo@virgilio.it>
> Cc:  <monnier@iro.umontreal.ca>
> 
> The horizontal flickering has 2 cases:
> 
> 1) font-lock mode disabled.
> Current line has a single global box around current line 
> Moving cursor vertically produce 1 pixel flickering due to the left border 
> that adds 1 pixel.
> Moving cursor horizontal (along the same line) produce flickering crossing 
> parenthesis when paren-mode is enabled. 2 more pixels if the matching 
> one is in another line, 4 more pixels if on the same. This because it draw 
> a box on highlight parenthesis adding  2 pixels for box.

This is the same problem as with stretches of white space.  Its reason
is separate from the one that causes the entire line to shift one
pixel to the right when the line thickness is -1.

> 2) Font-lock-mode enabled.
> Current line seems to have a single global box but looking careful it has 
> many consecutive boxes, one for every font-lock-face.

Same as above: a different reason.

> Moving cursor vertical increase current line length of one pixel for box 
> (cab be very big) producing flickering.

This is done deliberately, as I show in the code snippets I posted.
We are discussing why was this done, and will see whether and how to
fix that after we understand the reason(s).

> This happens also in line without space and tab like this no sense line:
> void{(if(a<b)while(c=d)do)switch(e)

Same as above: a different reason.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-11-29 19:06           ` Stefan Monnier
@ 2012-12-03  9:29             ` Kenichi Handa
  2012-12-03 16:33               ` Eli Zaretskii
  0 siblings, 1 reply; 28+ messages in thread
From: Kenichi Handa @ 2012-12-03  9:29 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 13011, mario.giovinazzo

In article <jwvhao8z0y8.fsf-monnier+emacs@gnu.org>, Stefan Monnier <monnier@iro.umontreal.ca> writes:

> > I made a provisional change that behaves with left and right borders
> > like it does with horizontal ones, and it seems to work, at least with
> > character display (didn't text with images, image slices, composite
> > characters, etc.).  But I'd like to ask Handa-san (CC'ed), who wrote
> > the code for this feature (almost 12 years ago!), whether he might
> > remember why the code deliberately makes the left and right borders
> > behave differently from top and bottom ones.

> I'm curious as well.  The only think that comes to mind is that in most
> fonts, there's usually some empty pixel-line(s) at the top and the
> bottom, whereas there often't isn't any empty pixel-lines at all on the
> left (and/or on the right) side.  So there's more risk of overwriting
> useful pixels on the left&right than at top&bottom.

Yes.  That's the reason of this asymmetry.  The original
intention of this feature was to make modeline occupy only
canonical line height even with the current style.

---
Kenichi Handa
handa@gnu.org






^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03  9:29             ` Kenichi Handa
@ 2012-12-03 16:33               ` Eli Zaretskii
  2012-12-03 16:44                 ` Drew Adams
  2012-12-04  0:13                 ` Kenichi Handa
  0 siblings, 2 replies; 28+ messages in thread
From: Eli Zaretskii @ 2012-12-03 16:33 UTC (permalink / raw)
  To: Kenichi Handa; +Cc: mario.giovinazzo, 13011

> From: Kenichi Handa <handa@gnu.org>
> Cc: eliz@gnu.org,  mario.giovinazzo@virgilio.it,  13011@debbugs.gnu.org
> Date: Mon, 03 Dec 2012 18:29:18 +0900
> 
> In article <jwvhao8z0y8.fsf-monnier+emacs@gnu.org>, Stefan Monnier <monnier@iro.umontreal.ca> writes:
> 
> > > I made a provisional change that behaves with left and right borders
> > > like it does with horizontal ones, and it seems to work, at least with
> > > character display (didn't text with images, image slices, composite
> > > characters, etc.).  But I'd like to ask Handa-san (CC'ed), who wrote
> > > the code for this feature (almost 12 years ago!), whether he might
> > > remember why the code deliberately makes the left and right borders
> > > behave differently from top and bottom ones.
> 
> > I'm curious as well.  The only think that comes to mind is that in most
> > fonts, there's usually some empty pixel-line(s) at the top and the
> > bottom, whereas there often't isn't any empty pixel-lines at all on the
> > left (and/or on the right) side.  So there's more risk of overwriting
> > useful pixels on the left&right than at top&bottom.
> 
> Yes.  That's the reason of this asymmetry.  The original
> intention of this feature was to make modeline occupy only
> canonical line height even with the current style.

So does anyone object to lifting this limitation, even though it might
degrade the quality of displaying the first and the last characters in
the run of characters that have the box face?





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 16:33               ` Eli Zaretskii
@ 2012-12-03 16:44                 ` Drew Adams
  2012-12-03 18:08                   ` Eli Zaretskii
  2012-12-04  0:13                 ` Kenichi Handa
  1 sibling, 1 reply; 28+ messages in thread
From: Drew Adams @ 2012-12-03 16:44 UTC (permalink / raw)
  To: 'Eli Zaretskii', 'Kenichi Handa'; +Cc: 13011, mario.giovinazzo

> So does anyone object to lifting this limitation, even though it might
> degrade the quality of displaying the first and the last characters in
> the run of characters that have the box face?

It's not obvious to me what that means for users.  Why don't you post before and
after images so we can judge?

Or if this affects something other than the visual appearance, so images won't
show the difference, please explain what this will change for users.

And what is the tradeoff for this "degrading"?  What are users gaining by this
sacrifice?

Thx.






^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 16:44                 ` Drew Adams
@ 2012-12-03 18:08                   ` Eli Zaretskii
  2012-12-03 18:41                     ` Drew Adams
  0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2012-12-03 18:08 UTC (permalink / raw)
  To: Drew Adams; +Cc: 13011, mario.giovinazzo

> From: "Drew Adams" <drew.adams@oracle.com>
> Cc: <mario.giovinazzo@virgilio.it>, <13011@debbugs.gnu.org>
> Date: Mon, 3 Dec 2012 08:44:39 -0800
> 
> > So does anyone object to lifting this limitation, even though it might
> > degrade the quality of displaying the first and the last characters in
> > the run of characters that have the box face?
> 
> It's not obvious to me what that means for users.  Why don't you post before and
> after images so we can judge?

The examples I have don't show any significant effect.  But I can
explain how you can experiment and see yourself.

Evaluate this:

  (custom-set-variables '(global-hl-line-mode t))
  (custom-set-faces '(hl-line ((t (:box (:line-width -1 :color "gray50"))))))

Then visit any files you like, and move cursor vertically.  You will
see that the text of the current line moves 1 pixel to the right when
you move cursor into that line.  This 1-pixel move is to leave enough
space for the 1-pixel border of the box on the left side of the line,
so that the first character is displayed with all its pixels visible.

The change that is being requested here is to prevent that 1-pixel
shift, which means the box border will be drawn ON the left-most
character, obscuring some of its pixels on the left.

For a more prominent effect, replace -1 above with -4.

> And what is the tradeoff for this "degrading"?  What are users gaining by this
> sacrifice?

The gain is that, with the above settings in effect, the text of a
line will not shift to the left when cursor moves into that line.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 18:08                   ` Eli Zaretskii
@ 2012-12-03 18:41                     ` Drew Adams
  2012-12-03 18:56                       ` Eli Zaretskii
  0 siblings, 1 reply; 28+ messages in thread
From: Drew Adams @ 2012-12-03 18:41 UTC (permalink / raw)
  To: 'Eli Zaretskii'; +Cc: 13011, mario.giovinazzo

[-- Attachment #1: Type: text/plain, Size: 2482 bytes --]

Thanks for the explanation and experiment.

Apart from that example, I imagine that this also affects any text that uses a
face that has a box with a negative :line-width.  Is that correct?

If so, that will impact faces that I use.  And IIUC, it means that the text
displayed in the boxed face will have its first and last chars partly obscured
by the box border.  Is that right?

If so, I would object.  Most uses of such faces are not like the hl-line
example, where there is a lot of text so faced.  Most uses (most of mine, at
least) are short bits of text, such as words.  And for these uses it is more
important that the first and last chars be displayed clearly (entirely).  I even
use a boxed face for some single characters (including using it for face
`escape-glyph').

I guess I would not object to making such a change for situations where the
chars to be partly obscured are whitespace only.  But I do object to overwriting
typical chars such as those with word or symbol syntax.

At least I think I object.  This change seems like regression, not improvement.

Attached is a screenshot from emacs -Q.  IIUC, you are saying that instead of
the text shown in mode-line-highlight face being slightly misaligned wrt the
other text, so that the `a' is not partly obscured by the left box border, the
text would be aligned with the others and the boxed `a' would be partly obscured
by the left box border.

OK, so by default the boxing here is 2, not -2, but if you set it to -2 that
does not change the argument/situation, AFAICT.  Likewise, if I use 2 or 4 in
your example test I see the same effect of the text moving slightly to the right
as it is highlighted.  Is the proposed change only a "fix" for negative values
or does it affect also positive values?

What is the motivation for this change?  Is it only in order to have fixed-width
text be better aligned? To me, that is less important than for the text to be
clearly visible - esp. for single words etc.

The boxing is supposed to make the text stand out, not make it harder to read.
This change seems to go against the usefulness of boxed faces.

Would it be possible for this to be a user choice?  E.g., could this perhaps be
added to `box' as another attribute, in addition to width, color, and style?  If
so, that would perhaps be a solution everyone could live with.  If so, I would
suggest that the default be the current behavior (clear text, even if slightly
misaligned).

Just one opinion, of course.

[-- Attachment #2: throw-boxed-face.png --]
[-- Type: image/png, Size: 27111 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 18:41                     ` Drew Adams
@ 2012-12-03 18:56                       ` Eli Zaretskii
  2012-12-03 19:09                         ` Drew Adams
  0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2012-12-03 18:56 UTC (permalink / raw)
  To: Drew Adams; +Cc: 13011, mario.giovinazzo

> From: "Drew Adams" <drew.adams@oracle.com>
> Cc: <handa@gnu.org>, <mario.giovinazzo@virgilio.it>, <13011@debbugs.gnu.org>
> Date: Mon, 3 Dec 2012 10:41:52 -0800
> 
> Apart from that example, I imagine that this also affects any text that uses a
> face that has a box with a negative :line-width.  Is that correct?

Yes.

> If so, that will impact faces that I use.  And IIUC, it means that the text
> displayed in the boxed face will have its first and last chars partly obscured
> by the box border.  Is that right?

Right.

> I guess I would not object to making such a change for situations where the
> chars to be partly obscured are whitespace only.  But I do object to overwriting
> typical chars such as those with word or symbol syntax.

How about doing that only for 1-pixel borders?

> Attached is a screenshot from emacs -Q.  IIUC, you are saying that instead of
> the text shown in mode-line-highlight face being slightly misaligned wrt the
> other text, so that the `a' is not partly obscured by the left box border, the
> text would be aligned with the others and the boxed `a' would be partly obscured
> by the left box border.

Yes, that's it.

> Is the proposed change only a "fix" for negative values or does it
> affect also positive values?

Only negative values will be affected.

> What is the motivation for this change?

See the beginning of this bug report: when a box face is used for
hl-line mode, moving cursor vertically produces an annoying shift of
the lines as the cursor moves through them.

> Would it be possible for this to be a user choice?

It's possible.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 18:56                       ` Eli Zaretskii
@ 2012-12-03 19:09                         ` Drew Adams
  2012-12-03 21:04                           ` Eli Zaretskii
  0 siblings, 1 reply; 28+ messages in thread
From: Drew Adams @ 2012-12-03 19:09 UTC (permalink / raw)
  To: 'Eli Zaretskii'; +Cc: 13011, mario.giovinazzo

> > I guess I would not object to making such a change for 
> > situations where the chars to be partly obscured are
> > whitespace only.  But I do object to overwriting
> > typical chars such as those with word or symbol syntax.
> 
> How about doing that only for 1-pixel borders?

Doing what?  Making the change or making the change only for whitespace?

Either way, I don't see why the width would make a difference.  What is the
rationale?

> Yes, that's it.
> 
> > Is the proposed change only a "fix" for negative values or does it
> > affect also positive values?
> 
> Only negative values will be affected.

Why?  The same jerkiness from alignment change occurs for both positive and
negative, AFAICT.

> > What is the motivation for this change?
> 
> See the beginning of this bug report: when a box face is used for
> hl-line mode, moving cursor vertically produces an annoying shift of
> the lines as the cursor moves through them.

Try it with a positive width - same thing.

Again, hl-line boxing is hardly typical, I think (again, not at all typical for
my use, at least).  More typical is boxing a word or two.

And one could even argue that that jerkiness was a feature (!) for hl-line mode.
Anyway, hl-line mode should not be important to this - boxing is for many more
use cases than that.

> > Would it be possible for this to be a user choice?
> 
> It's possible.

That I would be in favor of.  Simply changing the behavior/appearance without
user choice, I would be against.  Again, just one opinion, of course.






^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 19:09                         ` Drew Adams
@ 2012-12-03 21:04                           ` Eli Zaretskii
  2012-12-03 22:20                             ` Stefan Monnier
  2012-12-03 22:21                             ` Drew Adams
  0 siblings, 2 replies; 28+ messages in thread
From: Eli Zaretskii @ 2012-12-03 21:04 UTC (permalink / raw)
  To: Drew Adams; +Cc: 13011, mario.giovinazzo

> From: "Drew Adams" <drew.adams@oracle.com>
> Cc: <handa@gnu.org>, <mario.giovinazzo@virgilio.it>, <13011@debbugs.gnu.org>
> Date: Mon, 3 Dec 2012 11:09:13 -0800
> 
> > > I guess I would not object to making such a change for 
> > > situations where the chars to be partly obscured are
> > > whitespace only.  But I do object to overwriting
> > > typical chars such as those with word or symbol syntax.
> > 
> > How about doing that only for 1-pixel borders?
> 
> Doing what?  Making the change or making the change only for whitespace?

The former.

> Either way, I don't see why the width would make a difference.  What is the
> rationale?

1 pixel runs a very small risk of obscuring the character in the same
cell.

> > > Is the proposed change only a "fix" for negative values or does it
> > > affect also positive values?
> > 
> > Only negative values will be affected.
> 
> Why?  The same jerkiness from alignment change occurs for both positive and
> negative, AFAICT.

Yes, that's true.  But negative thickness does not enlarge the
vertical dimensions of character cells, whereas it does enlarge the
horizontal dimensions.  The request is to remove this asymmetry, as
the ELisp manual seems to promise:

    `(:line-width WIDTH :color COLOR :style STYLE)'
          This way you can explicitly specify all aspects of the box.
          The value WIDTH specifies the width of the lines to draw; it
          defaults to 1.  A negative width -N means to draw a line of
          width N that occupies the space of the underlying text, thus
          avoiding any increase in the character height or width.

But in fact, character width _is_ increased.

> > > What is the motivation for this change?
> > 
> > See the beginning of this bug report: when a box face is used for
> > hl-line mode, moving cursor vertically produces an annoying shift of
> > the lines as the cursor moves through them.
> 
> Try it with a positive width - same thing.

Yes, but the above says negative values should not have that effect.

> > > Would it be possible for this to be a user choice?
> > 
> > It's possible.
> 
> That I would be in favor of.  Simply changing the behavior/appearance without
> user choice, I would be against.  Again, just one opinion, of course.

What about using thickness of zero for drawing a 1-pixel border inside
of the character cell?





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 21:04                           ` Eli Zaretskii
@ 2012-12-03 22:20                             ` Stefan Monnier
  2012-12-03 22:51                               ` Drew Adams
  2012-12-03 22:21                             ` Drew Adams
  1 sibling, 1 reply; 28+ messages in thread
From: Stefan Monnier @ 2012-12-03 22:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 13011, mario.giovinazzo

>> That I would be in favor of.  Simply changing the behavior/appearance
>> without user choice, I would be against.  Again, just one opinion,
>> of course.
> What about using thickness of zero for drawing a 1-pixel border inside
> of the character cell?

I'd first like to hear why Drew uses negative thickness (and yet
wants it to be positive horizontally).

Also that's a hack, I can totally imagine someone using a very
high-resolution screen with largish fonts (measured in pixels) wanting
a -3 thickness around his hl-line box.


        Stefan





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 21:04                           ` Eli Zaretskii
  2012-12-03 22:20                             ` Stefan Monnier
@ 2012-12-03 22:21                             ` Drew Adams
  1 sibling, 0 replies; 28+ messages in thread
From: Drew Adams @ 2012-12-03 22:21 UTC (permalink / raw)
  To: 'Eli Zaretskii'; +Cc: 13011, mario.giovinazzo

> > > How about doing that only for 1-pixel borders?
> > 
> > Doing what?  Making the change or making the change only 
> > for whitespace?
> 
> The former.
> 
> > Either way, I don't see why the width would make a 
> > difference.  What is the rationale?
> 
> 1 pixel runs a very small risk of obscuring the character in the same
> cell.

I see.  Would probably need to see the effect to judge it.

> > > when a box face is used for
> > > hl-line mode, moving cursor vertically produces an 
> > > annoying shift of the lines as the cursor moves through them.
> > 
> > Try it with a positive width - same thing.
> 
> Yes, but the above says negative values should not have that effect.

Hm.  Is the problem the annoyance of the jerkiness or the fact that the doc does
not describe that jerkiness in the case of a negative value?

I would expect (imagine) that it is the jerkiness that is the problem.

> > > > Would it be possible for this to be a user choice?
> > > 
> > > It's possible.
> > 
> > That I would be in favor of.  Simply changing the 
> > behavior/appearance without user choice, I would be against.
> > Again, just one opinion, of course.
> 
> What about using thickness of zero for drawing a 1-pixel border inside
> of the character cell?

If the problem is only for a 1-pixel inside border, then perhaps that would be
the answer.  If the problem is for any number of pixels or for both inside and
outside borders (or both), then it would be appropriate to add a separate
attribute, independent from the width.

As far as I am concerned, if the only change is to add a new 0-width behavior
that produces a 1-pixel inside border that partially obscures the text, I would
have no problem with that.  In that case, IIUC, the existing attributes and
their values all would do the same thing they do now.  Currently, AFAICT, a
value of 0 means no box is shown.

On the other hand, any (existing or future) code that increments/decrements the
width would then be confronted with an anomaly, and if it expected a value of 0
to remove the box in that context, that would no longer work.

A new, independent attribute would be cleaner, but perhaps it is more difficult
to implement.






^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 22:20                             ` Stefan Monnier
@ 2012-12-03 22:51                               ` Drew Adams
  0 siblings, 0 replies; 28+ messages in thread
From: Drew Adams @ 2012-12-03 22:51 UTC (permalink / raw)
  To: 'Stefan Monnier', 'Eli Zaretskii'; +Cc: 13011, mario.giovinazzo

> I'd first like to hear why Drew uses negative thickness (and yet
> wants it to be positive horizontally).

IIRC, I use negative thickness mainly so the height is not increased.  I
typically do not care so much about the width (length) of a boxed word.  But I
do not want added border pixels to change the line height etc.

It really doesn't matter why or when or whether I use negative thickness.  The
question is which of these is the case:

1. The box left & right borders should be allowed to bump into the text that is
boxed.

2. Instead, the box should be shifted to the right because we have added extra
pixel(s) for the box border to the left of the text.

3. We should let users decide between #1 and #2.  For example, using a new box
attribute.

It's really not about me.  It's somewhat about how users use this today, and
what they expect.  But it's also about how users might use it (whether they do
or do not today) and what a user might expect from it.

> Also that's a hack, I can totally imagine someone using a very
> high-resolution screen with largish fonts (measured in pixels) wanting
> a -3 thickness around his hl-line box.

Me too.






^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-03 16:33               ` Eli Zaretskii
  2012-12-03 16:44                 ` Drew Adams
@ 2012-12-04  0:13                 ` Kenichi Handa
  1 sibling, 0 replies; 28+ messages in thread
From: Kenichi Handa @ 2012-12-04  0:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: mario.giovinazzo, 13011

In article <83ip8jrt7p.fsf@gnu.org>, Eli Zaretskii <eliz@gnu.org> writes:

> So does anyone object to lifting this limitation, even though it might
> degrade the quality of displaying the first and the last characters in
> the run of characters that have the box face?

I don't object to add a feature of drawing box edges inside
the left and right of characters, but I think it is better
to keep the current asymmetric feature too.

How about allowing (VWIDTH . HWIDTH) as a value of :line-width?

---
Kenichi Handa
handa@gnu.org





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-11-30  8:13 ` bug#13011: 24.2; " Eli Zaretskii
@ 2012-12-11 12:26   ` Eli Zaretskii
  2012-12-11 14:01     ` Stefan Monnier
  0 siblings, 1 reply; 28+ messages in thread
From: Eli Zaretskii @ 2012-12-11 12:26 UTC (permalink / raw)
  To: mario.giovinazzo; +Cc: 13011

> Date: Fri, 30 Nov 2012 10:13:30 +0200
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: 13011@debbugs.gnu.org
> 
> > Date: Fri, 30 Nov 2012 01:45:30 +0100 (CET)
> > From: "mario.giovinazzo@virgilio.it" <mario.giovinazzo@virgilio.it>
> > Cc:  <monnier@iro.umontreal.ca>
> > 
> > The horizontal flickering has 2 cases:
> > 
> > 1) font-lock mode disabled.
> > Current line has a single global box around current line 
> > Moving cursor vertically produce 1 pixel flickering due to the left border 
> > that adds 1 pixel.
> > Moving cursor horizontal (along the same line) produce flickering crossing 
> > parenthesis when paren-mode is enabled. 2 more pixels if the matching 
> > one is in another line, 4 more pixels if on the same. This because it draw 
> > a box on highlight parenthesis adding  2 pixels for box.
> 
> This is the same problem as with stretches of white space.  Its reason
> is separate from the one that causes the entire line to shift one
> pixel to the right when the line thickness is -1.
> 
> > 2) Font-lock-mode enabled.
> > Current line seems to have a single global box but looking careful it has 
> > many consecutive boxes, one for every font-lock-face.
> 
> Same as above: a different reason.

This part of the bug is now fixed in revision 111191 on the trunk.

For the rest of the bug I'm awaiting the decision wrt how to treat
vertical box borders whose width is negative.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: 24.2; Text flickering moving cursor with box around text enabled
  2012-12-11 12:26   ` Eli Zaretskii
@ 2012-12-11 14:01     ` Stefan Monnier
  0 siblings, 0 replies; 28+ messages in thread
From: Stefan Monnier @ 2012-12-11 14:01 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 13011, mario.giovinazzo

> For the rest of the bug I'm awaiting the decision wrt how to treat
> vertical box borders whose width is negative.

I think the suggestion to support a new box width specification of the
form (WIDTH . HEIGHT) is the best option.  So for backward
compatibility -N will mean (N . -N) and if someone wants "all inside, no
flicker" she can use (-N . -N).


        Stefan





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: Patch: Text flickering moving cursor with box around text enabled
  2012-11-27 10:42 bug#13011: 24.2; Text flickering moving cursor with box around text enabled mario giovinazzo
  2012-11-27 17:43 ` Eli Zaretskii
@ 2018-01-19 18:08 ` Alexandre Adolphe
  2019-08-10 21:21 ` bug#13011: [PATCH] " Alexandre Adolphe
  2 siblings, 0 replies; 28+ messages in thread
From: Alexandre Adolphe @ 2018-01-19 18:08 UTC (permalink / raw)
  To: 13011


[-- Attachment #1.1: Type: text/plain, Size: 1374 bytes --]

Hi,

I run into this issue so I tried to fix it to go into the emacs core code.
I followed the suggestion made in the bug and set box attribute to be
in the form (width . height). I tested it on windows and gnu/linux system
and on a mac os virtual machine but I am not sure to have tested all the
possible drawing as there are plenty of them. I tested both text box
and image relief.
I would appreciate that other people (especially those who use CAIRO
and those under real os x machine) confirm that the result is correct.

My simple test script :
----
(defun test_box_around_text (s)
  (save-excursion
    (goto-char (point-min))
    (insert "ABCDE\nABCDE\nABCDE\n")
    (put-text-property 8 11 'font-lock-face `(:box (:line-width ,s :color
"red")))
    ;; (put-text-property 8 11 'font-lock-face `(:box (:line-width ,s
:color "white" :style released-button)))
    ))

(test_box_around_text 4)
(test_box_around_text -4)
(test_box_around_text '(4 . -4))
(test_box_around_text '(-4 . 4))
(test_box_around_text '(-4 . -4))
(test_box_around_text '(4 . 0))
(test_box_around_text '(0 . 4))
(test_box_around_text '(4 . 1))
(test_box_around_text '(1 . 4))
(test_box_around_text '(-4 . 1))
(test_box_around_text '(1 . -4))

(save-excursion
    (goto-char (point-min))
    (insert-image
     (create-image
      "splash.svg" nil nil :relief 12)))
----

Thanks in advance,
Alexandre

[-- Attachment #1.2: Type: text/html, Size: 1976 bytes --]

[-- Attachment #2: 0001-Allow-negative-line-width-for-box-face-attribute.patch --]
[-- Type: text/x-patch, Size: 41262 bytes --]

From 8108d7e5bf3f4afe5918adbed17bf36c5930c709 Mon Sep 17 00:00:00 2001
From: Alexandre Adolphe <alexandre.adolphe@gmail.com>
Date: Fri, 19 Jan 2018 16:06:47 +0100
Subject: [PATCH] Allow negative line width for :box face attribute

Separate values for box line width and height and allow both to be
negative which makes the visual width and height of the boxed string
unchanged (Bug#13011).

* doc/lispref/display.texi (Face Attributes): Modify :box attribute
  description to reflect the new possibilities.
* src/dispextern.h (face): Use two int for box horizontal and vertical
  line width.

* src/nsfont.m (nsfont_draw): Use new face attributes.
* src/nsterm.m (ns_draw_box, ns_draw_relief): Support separated
  horizontal and vertical box line width.
  (ns_dumpglyphs_box_or_relief, ns_maybe_dumpglyphs_background)
  (ns_dumpglyphs_image, ns_draw_glyph_string_foreground)
  (ns_draw_composite_glyph_string_foreground): Use new face attributes.

* src/w32term.c (w32_draw_box_rect, w32_draw_relief_rect): Support
  separated horizontal and vertical box line width.
  (x_draw_glyph_string_background, x_draw_glyph_string_foreground)
  (x_draw_composite_glyph_string_foreground)
  (x_draw_glyphless_glyph_string_foreground)
  (x_draw_glyph_string_box, x_draw_image_foreground)
  (x_draw_image_relief, w32_draw_image_foreground_1)
  (x_draw_image_glyph_string): Use new face attributes.

* src/xfaces.c (Sinternal_set_lisp_face_attribute, realize_x_face):
  Accept box attribute as a list of two ints.

* src/xdisp.c (estimate_mode_line_height, produce_image_glyph)
  (produce_xwidget_glyph, x_produce_glyphs): Use new face attributes.
* src/xterm.c (x_draw_box_rect, x_draw_relief_rect): Support separated
  horizontal and vertical box line width.
  (x_draw_glyph_string_background, x_draw_glyph_string_foreground)
  (x_draw_composite_glyph_string_foreground)
  (x_draw_glyphless_glyph_string_foreground)
  (x_draw_glyph_string_box, x_draw_image_foreground)
  (x_draw_image_relief, x_draw_image_foreground_1)
  (x_draw_image_glyph_string): Use new face attributes.
---
 doc/lispref/display.texi |  15 +++---
 src/dispextern.h         |  17 ++++---
 src/nsfont.m             |   7 +--
 src/nsterm.m             |  53 ++++++++++----------
 src/w32term.c            |  53 ++++++++++----------
 src/xdisp.c              | 123 ++++++++++++++++++++---------------------------
 src/xfaces.c             |  23 ++++++---
 src/xterm.c              | 111 ++++++++++++++++++++----------------------
 8 files changed, 200 insertions(+), 202 deletions(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 921fd10..b0e4372 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -2366,12 +2366,15 @@ Face Attributes
 @item @var{color}
 Draw a box with lines of width 1, in color @var{color}.
 
-@item @code{(:line-width @var{width} :color @var{color} :style @var{style})}
-This way you can explicitly specify all aspects of the box.  The value
-@var{width} specifies the width of the lines to draw; it defaults to
-1.  A negative width @var{-n} means to draw a line of width @var{n}
-whose top and bottom parts occupy the space of the underlying text,
-thus avoiding any increase in the character height.
+@item @code{(:line-width (@var{vwidth} . @var{hwidth}) :color @var{color} :style @var{style})}
+This way you can explicitly specify all aspects of the box.  The values
+@var{vwidth} and @var{hwidth} specifies respectively the width of the
+vertcal and horizontal lines to draw; they default to (1 . 1).
+A negative (horizontal or vertical) width @var{-n} means to draw a line
+of width @var{n} that occupies the space of the underlying text, thus
+avoiding any increase in the character width or height. For simplification
+the width could be specified with only a single number @var{n} instead
+of a list, such case is equivalent to (abs(@var{n}) . @var{n}).
 
 The value @var{color} specifies the color to draw with.  The default is
 the foreground color of the face for simple boxes, and the background
diff --git a/src/dispextern.h b/src/dispextern.h
index 441361b..5b75a34 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1620,12 +1620,17 @@ struct face
   int fontset;
 
   /* Non-zero means characters in this face have a box of that
-     thickness around them.  If this value is negative, its absolute
-     value indicates the thickness, and the horizontal (top and
-     bottom) borders of box are drawn inside of the character glyphs'
-     area.  The vertical (left and right) borders of the box are drawn
-     in the same way as when this value is positive.  */
-  int box_line_width;
+     thickness around them. Vertical (left and right) and horizontal
+     (top and bottom) borders size can be set separatedly using an
+     associated list of two ints in the form
+     (vertical_size . horizontal_size). In case one of the value is
+     negative, its absolute value indicates the thickness, and the
+     borders of box are drawn inside of the character glyphs' area
+     potentially over the glyph itself but the glyph drawing size is
+     not increase. If a (signed) int N is use instead of a list, it
+     is the same as setting ( abs(N) . N ) values. */
+  int box_vertical_line_width;
+  int box_horizontal_line_width;
 
   /* Type of box drawn.  A value of FACE_NO_BOX means no box is drawn
      around text in this face.  A value of FACE_SIMPLE_BOX means a box
diff --git a/src/nsfont.m b/src/nsfont.m
index 8b42102..a066d91 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -1042,7 +1042,7 @@ is false when (FROM > 0 || TO < S->nchars). */
 
   r.origin.x = s->x;
   if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p)
-    r.origin.x += abs (s->face->box_line_width);
+    r.origin.x += max (s->face->box_vertical_line_width, 0);
 
   r.origin.y = s->y;
   r.size.height = FONT_HEIGHT (font);
@@ -1104,7 +1104,7 @@ is false when (FROM > 0 || TO < S->nchars). */
     {
       NSRect br = r;
       int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
-      int mbox_line_width = max (s->face->box_line_width, 0);
+      int mbox_line_width = max (s->face->box_vertical_line_width, 0);
 
       if (s->row->full_width_p)
         {
@@ -1128,9 +1128,10 @@ is false when (FROM > 0 || TO < S->nchars). */
         }
       else
         {
-          int correction = abs (s->face->box_line_width)+1;
+          int correction = abs (s->face->box_horizontal_line_width)+1;
           br.origin.y += correction;
           br.size.height -= 2*correction;
+          correction = abs (s->face->box_vertical_line_width)+1;
           br.origin.x += correction;
           br.size.width -= 2*correction;
         }
diff --git a/src/nsterm.m b/src/nsterm.m
index d2927d2..5c1b8bf 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3445,8 +3445,8 @@ larger if there are taller display elements (e.g., characters
 }
 
 static void
-ns_draw_box (NSRect r, CGFloat thickness, NSColor *col,
-             char left_p, char right_p)
+ns_draw_box (NSRect r, CGFloat vthickness, CGFloat hthickness,
+             NSColor *col, char left_p, char right_p)
 /* --------------------------------------------------------------------------
     Draw an unfilled rect inside r, optionally leaving left and/or right open.
     Note we can't just use an NSDrawRect command, because of the possibility
@@ -3457,28 +3457,28 @@ larger if there are taller display elements (e.g., characters
   [col set];
 
   /* top, bottom */
-  s.size.height = thickness;
+  s.size.height = hthickness;
   NSRectFill (s);
-  s.origin.y += r.size.height - thickness;
+  s.origin.y += r.size.height - hthickness;
   NSRectFill (s);
 
   s.size.height = r.size.height;
   s.origin.y = r.origin.y;
 
   /* left, right (optional) */
-  s.size.width = thickness;
+  s.size.width = vthickness;
   if (left_p)
     NSRectFill (s);
   if (right_p)
     {
-      s.origin.x += r.size.width - thickness;
+      s.origin.x += r.size.width - vthickness;
       NSRectFill (s);
     }
 }
 
 
 static void
-ns_draw_relief (NSRect r, int thickness, char raised_p,
+ns_draw_relief (NSRect r, int vthickness, int hthickness, char raised_p,
                char top_p, char bottom_p, char left_p, char right_p,
                struct glyph_string *s)
 /* --------------------------------------------------------------------------
@@ -3528,27 +3528,27 @@ larger if there are taller display elements (e.g., characters
   /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
 
   /* top */
-  sr.size.height = thickness;
+  sr.size.height = hthickness;
   if (top_p) NSRectFill (sr);
 
   /* left */
   sr.size.height = r.size.height;
-  sr.size.width = thickness;
+  sr.size.width = vthickness;
   if (left_p) NSRectFill (sr);
 
   [(raised_p ? darkCol : lightCol) set];
 
   /* bottom */
   sr.size.width = r.size.width;
-  sr.size.height = thickness;
-  sr.origin.y += r.size.height - thickness;
+  sr.size.height = hthickness;
+  sr.origin.y += r.size.height - hthickness;
   if (bottom_p) NSRectFill (sr);
 
   /* right */
   sr.size.height = r.size.height;
   sr.origin.y = r.origin.y;
-  sr.size.width = thickness;
-  sr.origin.x += r.size.width - thickness;
+  sr.size.width = vthickness;
+  sr.origin.x += r.size.width - vthickness;
   if (right_p) NSRectFill (sr);
 }
 
@@ -3577,7 +3577,7 @@ Function modeled after x_draw_glyph_string_box ().
   else
     face = s->face;
 
-  thickness = face->box_line_width;
+  thickness = face->box_vertical_line_width;
 
   NSTRACE ("ns_dumpglyphs_box_or_relief");
 
@@ -3602,14 +3602,15 @@ Function modeled after x_draw_glyph_string_box ().
   /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
   if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
     {
-      ns_draw_box (r, abs (thickness),
+      ns_draw_box (r, abs (thickness), abs (face->box_horizontal_line_width),
                    ns_lookup_indexed_color (face->box_color, s->f),
-                  left_p, right_p);
+                   left_p, right_p);
     }
   else
     {
-      ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
-                     1, 1, left_p, right_p, s);
+      ns_draw_relief (r, abs (thickness), abs (face->box_horizontal_line_width),
+		      s->face->box == FACE_RAISED_BOX,
+		      1, 1, left_p, right_p, s);
     }
 }
 
@@ -3625,7 +3626,7 @@ Function modeled after x_draw_glyph_string_box ().
 
   if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
     {
-      int box_line_width = max (s->face->box_line_width, 0);
+      int box_line_width = max (s->face->box_horizontal_line_width, 0);
       if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
 	  /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
 	     dimensions, since the actual glyphs might be much
@@ -3676,7 +3677,7 @@ Function modeled after x_draw_glyph_string_box ().
    -------------------------------------------------------------------------- */
 {
   EmacsImage *img = s->img->pixmap;
-  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
   int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
   int bg_x, bg_y, bg_height;
   int th;
@@ -3689,7 +3690,7 @@ Function modeled after x_draw_glyph_string_box ().
 
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   bg_x = x;
   bg_y =  s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
@@ -3788,7 +3789,7 @@ Function modeled after x_draw_glyph_string_box ().
       r.origin.y = y - th;
       r.size.width = s->slice.width + 2*th-1;
       r.size.height = s->slice.height + 2*th-1;
-      ns_draw_relief (r, th, raised_p,
+      ns_draw_relief (r, th, th, raised_p,
                       s->slice.y == 0,
                       s->slice.y + s->slice.height == s->img->height,
                       s->slice.x == 0,
@@ -3802,7 +3803,7 @@ Function modeled after x_draw_glyph_string_box ().
     {
       int thickness = abs (s->img->relief);
       if (thickness == 0) thickness = 1;
-      ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
+      ns_draw_box (br, thickness, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
     }
 }
 
@@ -3912,7 +3913,7 @@ overwriting cursor (usually when cursor on a tab) */
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -3938,7 +3939,7 @@ overwriting cursor (usually when cursor on a tab) */
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -3954,7 +3955,7 @@ overwriting cursor (usually when cursor on a tab) */
       if (s->cmp_from == 0)
         {
           NSRect r = NSMakeRect (s->x, s->y, s->width-1, s->height -1);
-          ns_draw_box (r, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
+          ns_draw_box (r, 1, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
         }
     }
   else if (! s->first_glyph->u.cmp.automatic)
diff --git a/src/w32term.c b/src/w32term.c
index 137c798..477f889 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -961,10 +961,10 @@ static void w32_draw_image_foreground_1 (struct glyph_string *, HBITMAP);
 static void x_clear_glyph_string_rect (struct glyph_string *, int,
                                        int, int, int);
 static void w32_draw_relief_rect (struct frame *, int, int, int, int,
-                                  int, int, int, int, int, int,
+                                  int, int, int, int, int, int, int,
                                   RECT *);
 static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
-                               int, bool, bool, RECT *);
+                               int, int, bool, bool, RECT *);
 
 
 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
@@ -1239,7 +1239,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
-      int box_line_width = max (s->face->box_line_width, 0);
+      int box_line_width = max (s->face->box_horizontal_line_width, 0);
 
 #if 0 /* TODO: stipple */
       if (s->stippled_p)
@@ -1285,7 +1285,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1343,7 +1343,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1440,7 +1440,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1699,7 +1699,7 @@ x_setup_relief_colors (struct glyph_string *s)
 static void
 w32_draw_relief_rect (struct frame *f,
 		      int left_x, int top_y, int right_x, int bottom_y,
-		      int width, int raised_p,
+		      int hwidth, int vwidth, int raised_p,
 		      int top_p, int bot_p, int left_p, int right_p,
 		      RECT *clip_rect)
 {
@@ -1716,14 +1716,14 @@ w32_draw_relief_rect (struct frame *f,
 
   /* Top.  */
   if (top_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < hwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     left_x + i * left_p, top_y + i,
 		     right_x - left_x - i * (left_p + right_p ) + 1, 1);
 
   /* Left.  */
   if (left_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < vwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     left_x + i, top_y + (i + 1) * top_p, 1,
 		     bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@@ -1735,14 +1735,14 @@ w32_draw_relief_rect (struct frame *f,
 
   /* Bottom.  */
   if (bot_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < hwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     left_x + i * left_p, bottom_y - i,
 		     right_x - left_x - i * (left_p + right_p) + 1, 1);
 
   /* Right.  */
   if (right_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < vwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     right_x - i, top_y + (i + 1) * top_p, 1,
 		     bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@@ -1762,31 +1762,31 @@ w32_draw_relief_rect (struct frame *f,
 
 static void
 w32_draw_box_rect (struct glyph_string *s,
-		   int left_x, int top_y, int right_x, int bottom_y, int width,
-                   bool left_p, bool right_p, RECT *clip_rect)
+		   int left_x, int top_y, int right_x, int bottom_y, int hwidth,
+		   int vwidth, bool left_p, bool right_p, RECT *clip_rect)
 {
   w32_set_clip_rectangle (s->hdc, clip_rect);
 
   /* Top.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
-		  left_x, top_y, right_x - left_x + 1, width);
+		  left_x, top_y, right_x - left_x + 1, hwidth);
 
   /* Left.  */
   if (left_p)
     {
       w32_fill_area (s->f, s->hdc, s->face->box_color,
-                     left_x, top_y, width, bottom_y - top_y + 1);
+                     left_x, top_y, vwidth, bottom_y - top_y + 1);
     }
 
   /* Bottom.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
-                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+                 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
 
   /* Right.  */
   if (right_p)
     {
       w32_fill_area (s->f, s->hdc, s->face->box_color,
-                     right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+                     right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
     }
 
   w32_set_clip_rectangle (s->hdc, NULL);
@@ -1812,7 +1812,7 @@ x_draw_glyph_string_box (struct glyph_string *s)
 		? s->first_glyph
 		: s->first_glyph + s->nchars - 1);
 
-  width = eabs (s->face->box_line_width);
+  width = eabs (s->face->box_vertical_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
   right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
@@ -1833,12 +1833,13 @@ x_draw_glyph_string_box (struct glyph_string *s)
   get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
-    w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
-                       left_p, right_p, &clip_rect);
+    w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, eabs (s->face->box_horizontal_line_width),
+                       width, left_p, right_p, &clip_rect);
   else
     {
       x_setup_relief_colors (s);
       w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
+                            eabs (s->face->box_horizontal_line_width),
                             width, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
@@ -1857,7 +1858,7 @@ x_draw_image_foreground (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -1950,7 +1951,7 @@ x_draw_image_relief (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2002,7 +2003,7 @@ x_draw_image_relief (struct glyph_string *s)
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  w32_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
+  w32_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
 			top_p, bot_p, left_p, right_p, &r);
 }
 
@@ -2022,7 +2023,7 @@ w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2131,8 +2132,8 @@ static void
 x_draw_image_glyph_string (struct glyph_string *s)
 {
   int x, y;
-  int box_line_hwidth = eabs (s->face->box_line_width);
-  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
+  int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
   int height, width;
   HBITMAP pixmap = 0;
 
diff --git a/src/xdisp.c b/src/xdisp.c
index d2bb47f..b82bd4b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1854,8 +1854,8 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
 	    {
 	      if (face->font)
 		height = normal_char_height (face->font, -1);
-	      if (face->box_line_width > 0)
-		height += 2 * face->box_line_width;
+	      if (face->box_horizontal_line_width > 0)
+		height += 2 * face->box_horizontal_line_width;
 	    }
 	}
 
@@ -27063,18 +27063,21 @@ produce_image_glyph (struct it *it)
 
   if (face->box != FACE_NO_BOX)
     {
-      if (face->box_line_width > 0)
+      if (face->box_horizontal_line_width > 0)
 	{
 	  if (slice.y == 0)
-	    it->ascent += face->box_line_width;
+	    it->ascent += face->box_horizontal_line_width;
 	  if (slice.y + slice.height == img->height)
-	    it->descent += face->box_line_width;
+	    it->descent += face->box_horizontal_line_width;
 	}
 
-      if (it->start_of_box_run_p && slice.x == 0)
-	it->pixel_width += eabs (face->box_line_width);
-      if (it->end_of_box_run_p && slice.x + slice.width == img->width)
-	it->pixel_width += eabs (face->box_line_width);
+      if (face->box_vertical_line_width > 0)
+	{
+	  if (it->start_of_box_run_p && slice.x == 0)
+	    it->pixel_width += face->box_vertical_line_width;
+	  if (it->end_of_box_run_p && slice.x + slice.width == img->width)
+	    it->pixel_width += face->box_vertical_line_width;
+	}
     }
 
   take_vertical_position_into_account (it);
@@ -27172,15 +27175,18 @@ produce_xwidget_glyph (struct it *it)
 
   if (face->box != FACE_NO_BOX)
     {
-      if (face->box_line_width > 0)
+      if (face->box_horizontal_line_width > 0)
 	{
-	  it->ascent += face->box_line_width;
-	  it->descent += face->box_line_width;
+	  it->ascent += face->box_horizontal_line_width;
+	  it->descent += face->box_horizontal_line_width;
 	}
 
-      if (it->start_of_box_run_p)
-	it->pixel_width += eabs (face->box_line_width);
-      it->pixel_width += eabs (face->box_line_width);
+      if (face->box_vertical_line_width > 0)
+	{
+	  if (it->start_of_box_run_p)
+	    it->pixel_width += face->box_vertical_line_width;
+	  it->pixel_width += face->box_vertical_line_width;
+	}
     }
 
   take_vertical_position_into_account (it);
@@ -27938,6 +27944,31 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
 }
 
 
+/* If face has a box, add the box thickness to the character
+   height.  If character has a box line to the left and/or
+   right, add the box line width to the character's width.  */
+#define IT_APPLY_FACE_BOX(it, face)				\
+  do {								\
+    if (face->box != FACE_NO_BOX)				\
+      {								\
+	int thick = face->box_horizontal_line_width;		\
+	if (thick > 0)						\
+	  {							\
+	    it->ascent += thick;				\
+	    it->descent += thick;				\
+	  }							\
+								\
+	thick = face->box_vertical_line_width;			\
+	if (thick > 0)						\
+	  {							\
+	    if (it->start_of_box_run_p)				\
+	      it->pixel_width += thick;				\
+	    if (it->end_of_box_run_p)				\
+	      it->pixel_width += thick;				\
+	  }							\
+      }								\
+    } while (false)
+
 /* RIF:
    Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct it in dispextern.h
@@ -28053,26 +28084,7 @@ x_produce_glyphs (struct it *it)
 	  if (stretched_p)
 	    it->pixel_width *= XFLOATINT (it->space_width);
 
-	  /* If face has a box, add the box thickness to the character
-	     height.  If character has a box line to the left and/or
-	     right, add the box line width to the character's width.  */
-	  if (face->box != FACE_NO_BOX)
-	    {
-	      int thick = face->box_line_width;
-
-	      if (thick > 0)
-		{
-		  it->ascent += thick;
-		  it->descent += thick;
-		}
-	      else
-		thick = -thick;
-
-	      if (it->start_of_box_run_p)
-		it->pixel_width += thick;
-	      if (it->end_of_box_run_p)
-		it->pixel_width += thick;
-	    }
+	  IT_APPLY_FACE_BOX(it, face);
 
 	  /* If face has an overline, add the height of the overline
 	     (1 pixel) and a 1 pixel margin to the character height.  */
@@ -28187,10 +28199,10 @@ x_produce_glyphs (struct it *it)
 
 	      if ((it->max_ascent > 0 || it->max_descent > 0)
 		  && face->box != FACE_NO_BOX
-		  && face->box_line_width > 0)
+		  && face->box_horizontal_line_width > 0)
 		{
-		  it->ascent += face->box_line_width;
-		  it->descent += face->box_line_width;
+		  it->ascent += face->box_horizontal_line_width;
+		  it->descent += face->box_horizontal_line_width;
 		}
 	      if (!NILP (height)
 		  && XINT (height) > it->ascent + it->descent)
@@ -28582,23 +28594,7 @@ x_produce_glyphs (struct it *it)
       it->pixel_width = cmp->pixel_width;
       it->ascent = it->phys_ascent = cmp->ascent;
       it->descent = it->phys_descent = cmp->descent;
-      if (face->box != FACE_NO_BOX)
-	{
-	  int thick = face->box_line_width;
-
-	  if (thick > 0)
-	    {
-	      it->ascent += thick;
-	      it->descent += thick;
-	    }
-	  else
-	    thick = - thick;
-
-	  if (it->start_of_box_run_p)
-	    it->pixel_width += thick;
-	  if (it->end_of_box_run_p)
-	    it->pixel_width += thick;
-	}
+      IT_APPLY_FACE_BOX(it, face);
 
       /* If face has an overline, add the height of the overline
 	 (1 pixel) and a 1 pixel margin to the character height.  */
@@ -28632,23 +28628,8 @@ x_produce_glyphs (struct it *it)
 	it->glyph_row->contains_overlapping_glyphs_p = true;
       it->ascent = it->phys_ascent = metrics.ascent;
       it->descent = it->phys_descent = metrics.descent;
-      if (face->box != FACE_NO_BOX)
-	{
-	  int thick = face->box_line_width;
+      IT_APPLY_FACE_BOX(it, face);
 
-	  if (thick > 0)
-	    {
-	      it->ascent += thick;
-	      it->descent += thick;
-	    }
-	  else
-	    thick = - thick;
-
-	  if (it->start_of_box_run_p)
-	    it->pixel_width += thick;
-	  if (it->end_of_box_run_p)
-	    it->pixel_width += thick;
-	}
       /* If face has an overline, add the height of the overline
 	 (1 pixel) and a 1 pixel margin to the character height.  */
       if (face->overline_p)
diff --git a/src/xfaces.c b/src/xfaces.c
index 3479799..0cb85f1 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2884,7 +2884,9 @@ FRAME 0 means change the face on all frames, and change the default
 
 	      if (EQ (k, QCline_width))
 		{
-		  if (!INTEGERP (v) || XINT (v) == 0)
+		  if ((!CONSP(v) || !INTEGERP (XCAR (v)) || XINT (XCAR (v)) == 0
+		                 || !INTEGERP (XCDR (v)) || XINT (XCDR (v)) == 0)
+		      && (!INTEGERP (v) || XINT (v) == 0))
 		    break;
 		}
 	      else if (EQ (k, QCcolor))
@@ -5524,7 +5526,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
       face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
 				    LFACE_BOX_INDEX);
       face->box = FACE_SIMPLE_BOX;
-      face->box_line_width = 1;
+      face->box_vertical_line_width = face->box_horizontal_line_width = 1;
     }
   else if (INTEGERP (box))
     {
@@ -5532,7 +5534,8 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
 	 face.  */
       eassert (XINT (box) != 0);
       face->box = FACE_SIMPLE_BOX;
-      face->box_line_width = XINT (box);
+      face->box_vertical_line_width = eabs(XINT (box));
+      face->box_horizontal_line_width = XINT (box);
       face->box_color = face->foreground;
       face->box_color_defaulted_p = true;
     }
@@ -5543,7 +5546,7 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
       face->box = FACE_SIMPLE_BOX;
       face->box_color = face->foreground;
       face->box_color_defaulted_p = true;
-      face->box_line_width = 1;
+      face->box_vertical_line_width = face->box_horizontal_line_width = 1;
 
       while (CONSP (box))
 	{
@@ -5559,8 +5562,16 @@ realize_x_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE])
 
 	  if (EQ (keyword, QCline_width))
 	    {
-	      if (INTEGERP (value) && XINT (value) != 0)
-		face->box_line_width = XINT (value);
+	      if (CONSP (value)) {
+		if (INTEGERP (XCAR (value)))
+		  face->box_vertical_line_width = XINT (XCAR (value));
+		if (INTEGERP (XCDR (value)))
+		  face->box_horizontal_line_width = XINT (XCDR (value));
+	      }
+	      else if (INTEGERP (value) && XINT (value) != 0) {
+		face->box_vertical_line_width = eabs (XINT (value));
+		face->box_horizontal_line_width = XINT (value);
+	      }
 	    }
 	  else if (EQ (keyword, QCcolor))
 	    {
diff --git a/src/xterm.c b/src/xterm.c
index 0a2068d..36692d3 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1528,10 +1528,10 @@ static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
 static void x_clear_glyph_string_rect (struct glyph_string *, int,
                                        int, int, int);
 static void x_draw_relief_rect (struct frame *, int, int, int, int,
-                                int, bool, bool, bool, bool, bool,
+                                int, int, bool, bool, bool, bool, bool,
                                 XRectangle *);
 static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
-                             int, bool, bool, XRectangle *);
+                             int, int, bool, bool, XRectangle *);
 static void x_scroll_bar_clear (struct frame *);
 
 #ifdef GLYPH_DEBUG
@@ -1794,7 +1794,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
-      int box_line_width = max (s->face->box_line_width, 0);
+      int box_line_width = max (s->face->box_horizontal_line_width, 0);
 
       if (s->stippled_p)
 	{
@@ -1837,7 +1837,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1886,7 +1886,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1978,7 +1978,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -2715,7 +2715,7 @@ x_setup_relief_colors (struct glyph_string *s)
 static void
 x_draw_relief_rect (struct frame *f,
 		    int left_x, int top_y, int right_x, int bottom_y,
-		    int width, bool raised_p, bool top_p, bool bot_p,
+		    int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
 		    bool left_p, bool right_p,
 		    XRectangle *clip_rect)
 {
@@ -2740,7 +2740,7 @@ x_draw_relief_rect (struct frame *f,
   if (left_p)
     {
       x_fill_rectangle (f, top_left_gc, left_x, top_y,
-			width, bottom_y + 1 - top_y);
+			vwidth, bottom_y + 1 - top_y);
       if (top_p)
 	corners |= 1 << CORNER_TOP_LEFT;
       if (bot_p)
@@ -2748,8 +2748,8 @@ x_draw_relief_rect (struct frame *f,
     }
   if (right_p)
     {
-      x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
-			width, bottom_y + 1 - top_y);
+      x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
+			vwidth, bottom_y + 1 - top_y);
       if (top_p)
 	corners |= 1 << CORNER_TOP_RIGHT;
       if (bot_p)
@@ -2759,25 +2759,25 @@ x_draw_relief_rect (struct frame *f,
     {
       if (!right_p)
 	x_fill_rectangle (f, top_left_gc, left_x, top_y,
-			  right_x + 1 - left_x, width);
+			  right_x + 1 - left_x, hwidth);
       else
 	x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
-				     right_x + 1 - left_x, width, 1);
+				     right_x + 1 - left_x, hwidth, 1);
     }
   if (bot_p)
     {
       if (!left_p)
-	x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
-			  right_x + 1 - left_x, width);
+	x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
+			  right_x + 1 - left_x, hwidth);
       else
 	x_fill_trapezoid_for_relief (f, bottom_right_gc,
-				     left_x, bottom_y + 1 - width,
-				     right_x + 1 - left_x, width, 0);
+				     left_x, bottom_y + 1 - hwidth,
+				     right_x + 1 - left_x, hwidth, 0);
     }
-  if (left_p && width != 1)
+  if (left_p && vwidth > 1)
     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
 		      1, bottom_y + 1 - top_y);
-  if (top_p && width != 1)
+  if (top_p && hwidth > 1)
     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
 		      right_x + 1 - left_x, 1);
   if (corners)
@@ -2811,12 +2811,12 @@ x_draw_relief_rect (struct frame *f,
   /* Top.  */
   if (top_p)
     {
-      if (width == 1)
+      if (hwidth == 1)
         XDrawLine (dpy, drawable, gc,
 		   left_x + left_p, top_y,
 		   right_x + !right_p, top_y);
 
-      for (i = 1; i < width; ++i)
+      for (i = 1; i < hwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   left_x  + i * left_p, top_y + i,
 		   right_x + 1 - i * right_p, top_y + i);
@@ -2825,13 +2825,10 @@ x_draw_relief_rect (struct frame *f,
   /* Left.  */
   if (left_p)
     {
-      if (width == 1)
+      if (vwidth == 1)
         XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
 
-      x_clear_area(f, left_x, top_y, 1, 1);
-      x_clear_area(f, left_x, bottom_y, 1, 1);
-
-      for (i = (width > 1 ? 1 : 0); i < width; ++i)
+      for (i = 1; i < vwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   left_x + i, top_y + (i + 1) * top_p,
 		   left_x + i, bottom_y + 1 - (i + 1) * bot_p);
@@ -2844,26 +2841,25 @@ x_draw_relief_rect (struct frame *f,
     gc = f->output_data.x->white_relief.gc;
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
-  if (width > 1)
-    {
-      /* Outermost top line.  */
-      if (top_p)
-        XDrawLine (dpy, drawable, gc,
-		   left_x  + left_p, top_y,
-		   right_x + !right_p, top_y);
+  /* Outermost top line.  */
+  if (top_p && hwidth > 1)
+    XDrawLine (dpy, drawable, gc,
+	       left_x  + left_p, top_y,
+	       right_x + !right_p, top_y);
 
-      /* Outermost left line.  */
-      if (left_p)
-        XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
-    }
+  /* Outermost left line.  */
+  if (left_p && vwidth > 1)
+    XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
 
   /* Bottom.  */
   if (bot_p)
     {
-      XDrawLine (dpy, drawable, gc,
-		 left_x + left_p, bottom_y,
-		 right_x + !right_p, bottom_y);
-      for (i = 1; i < width; ++i)
+      if (hwidth >= 1)
+        XDrawLine (dpy, drawable, gc,
+		   left_x + left_p, bottom_y,
+		   right_x + !right_p, bottom_y);
+
+      for (i = 1; i < hwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   left_x  + i * left_p, bottom_y - i,
 		   right_x + 1 - i * right_p, bottom_y - i);
@@ -2872,9 +2868,7 @@ x_draw_relief_rect (struct frame *f,
   /* Right.  */
   if (right_p)
     {
-      x_clear_area(f, right_x, top_y, 1, 1);
-      x_clear_area(f, right_x, bottom_y, 1, 1);
-      for (i = 0; i < width; ++i)
+      for (i = 0; i < vwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   right_x - i, top_y + (i + 1) * top_p,
 		   right_x - i, bottom_y + 1 - (i + 1) * bot_p);
@@ -2895,8 +2889,8 @@ x_draw_relief_rect (struct frame *f,
 
 static void
 x_draw_box_rect (struct glyph_string *s,
-		 int left_x, int top_y, int right_x, int bottom_y, int width,
-		 bool left_p, bool right_p, XRectangle *clip_rect)
+		 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
+		 int vwidth, bool left_p, bool right_p, XRectangle *clip_rect)
 {
   XGCValues xgcv;
 
@@ -2906,21 +2900,21 @@ x_draw_box_rect (struct glyph_string *s,
 
   /* Top.  */
   x_fill_rectangle (s->f, s->gc,
-		  left_x, top_y, right_x - left_x + 1, width);
+		  left_x, top_y, right_x - left_x + 1, hwidth);
 
   /* Left.  */
   if (left_p)
     x_fill_rectangle (s->f, s->gc,
-		    left_x, top_y, width, bottom_y - top_y + 1);
+		    left_x, top_y, vwidth, bottom_y - top_y + 1);
 
   /* Bottom.  */
   x_fill_rectangle (s->f, s->gc,
-		  left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+		  left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
 
   /* Right.  */
   if (right_p)
     x_fill_rectangle (s->f, s->gc,
-		    right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+		    right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
 
   XSetForeground (s->display, s->gc, xgcv.foreground);
   x_reset_clip_rectangles (s->f, s->gc);
@@ -2946,7 +2940,7 @@ x_draw_glyph_string_box (struct glyph_string *s)
 		? s->first_glyph
 		: s->first_glyph + s->nchars - 1);
 
-  width = eabs (s->face->box_line_width);
+  width = eabs (s->face->box_vertical_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
   right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
@@ -2967,12 +2961,13 @@ x_draw_glyph_string_box (struct glyph_string *s)
   get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
-    x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
-		     left_p, right_p, &clip_rect);
+    x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, eabs (s->face->box_horizontal_line_width),
+		     width, left_p, right_p, &clip_rect);
   else
     {
       x_setup_relief_colors (s);
       x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
+			  eabs (s->face->box_horizontal_line_width),
 			  width, raised_p, true, true, left_p, right_p,
 			  &clip_rect);
     }
@@ -2992,7 +2987,7 @@ x_draw_image_foreground (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -3087,7 +3082,7 @@ x_draw_image_relief (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -3138,7 +3133,7 @@ x_draw_image_relief (struct glyph_string *s)
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
+  x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
 		      top_p, bot_p, left_p, right_p, &r);
 }
 
@@ -3156,7 +3151,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -3252,8 +3247,8 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
 static void
 x_draw_image_glyph_string (struct glyph_string *s)
 {
-  int box_line_hwidth = eabs (s->face->box_line_width);
-  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
+  int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
   int height;
   Pixmap pixmap = None;
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#13011: [PATCH] Text flickering moving cursor with box around text enabled
  2012-11-27 10:42 bug#13011: 24.2; Text flickering moving cursor with box around text enabled mario giovinazzo
  2012-11-27 17:43 ` Eli Zaretskii
  2018-01-19 18:08 ` bug#13011: Patch: " Alexandre Adolphe
@ 2019-08-10 21:21 ` Alexandre Adolphe
  2019-08-20 13:44   ` Noam Postavsky
                     ` (2 more replies)
  2 siblings, 3 replies; 28+ messages in thread
From: Alexandre Adolphe @ 2019-08-10 21:21 UTC (permalink / raw)
  To: 13011


[-- Attachment #1.1: Type: text/plain, Size: 226 bytes --]

Hi,

After seeing that some people were interrest about this issue on reddit, I
rejump in this change. I saw that the customization of box were not
correctly done so I correct it.
Here is the updated patch.

Thanks,
Alexandre

[-- Attachment #1.2: Type: text/html, Size: 316 bytes --]

[-- Attachment #2: 0001-Allow-negative-line-width-for-box-face-attribute.patch --]
[-- Type: text/x-patch, Size: 44964 bytes --]

From 57318acff57f998805017ae9327601773e4881c9 Mon Sep 17 00:00:00 2001
From: Alexandre Adolphe <alexandre.adolphe@gmail.com>
Date: Sat, 10 Aug 2019 22:57:24 +0200
Subject: [PATCH] Allow negative line width for :box face attribute

Separate values for box line width and height and allow both to be
negative which makes the visual width and height of the boxed string
unchanged (Bug#13011).

* doc/lispref/display.texi (Face Attributes): Modify :box attribute
  description to reflect the new possibilities.
* lisp/cus-face.el (custom-face-attributes): Set box attribute to get
  two integer to set vertical and horizontal width and modify pre-filter
  to accept dotted list of two int as valid box attribute.
* src/dispextern.h (face): Use two int for box horizontal and vertical
  line width.

* src/nsfont.m (nsfont_draw): Use new face attributes.
* src/nsterm.m (ns_draw_box, ns_draw_relief): Support separated
  horizontal and vertical box line width.
  (ns_dumpglyphs_box_or_relief, ns_maybe_dumpglyphs_background)
  (ns_dumpglyphs_image, ns_draw_glyph_string_foreground)
  (ns_draw_composite_glyph_string_foreground): Use new face attributes.

* src/w32term.c (w32_draw_box_rect, w32_draw_relief_rect): Support
  separated horizontal and vertical box line width.
  (x_draw_glyph_string_background, x_draw_glyph_string_foreground)
  (x_draw_composite_glyph_string_foreground)
  (x_draw_glyphless_glyph_string_foreground)
  (x_draw_glyph_string_box, x_draw_image_foreground)
  (x_draw_image_relief, w32_draw_image_foreground_1)
  (x_draw_image_glyph_string): Use new face attributes.

* src/xfaces.c (Sinternal_set_lisp_face_attribute, realize_x_face):
  Accept box attribute as a list of two ints.

* src/xdisp.c (estimate_mode_line_height, produce_image_glyph)
  (produce_xwidget_glyph, x_produce_glyphs): Use new face attributes.
* src/xterm.c (x_draw_box_rect, x_draw_relief_rect): Support separated
  horizontal and vertical box line width.
  (x_draw_glyph_string_background, x_draw_glyph_string_foreground)
  (x_draw_composite_glyph_string_foreground)
  (x_draw_glyphless_glyph_string_foreground)
  (x_draw_glyph_string_box, x_draw_image_foreground)
  (x_draw_image_relief, x_draw_image_foreground_1)
  (x_draw_image_glyph_string): Use new face attributes.
---
 doc/lispref/display.texi |  15 +++--
 lisp/cus-face.el         |  16 +++--
 src/dispextern.h         |  17 ++++--
 src/nsfont.m             |   7 ++-
 src/nsterm.m             |  56 +++++++++---------
 src/w32term.c            |  59 ++++++++++---------
 src/xdisp.c              | 123 +++++++++++++++++----------------------
 src/xfaces.c             |  32 ++++++++--
 src/xterm.c              | 115 +++++++++++++++++-------------------
 9 files changed, 227 insertions(+), 213 deletions(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 7c0a56dcad..3588c5fd44 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -2413,12 +2413,15 @@ Face Attributes
 @item @var{color}
 Draw a box with lines of width 1, in color @var{color}.
 
-@item @code{(:line-width @var{width} :color @var{color} :style @var{style})}
-This way you can explicitly specify all aspects of the box.  The value
-@var{width} specifies the width of the lines to draw; it defaults to
-1.  A negative width @minus{}@var{n} means to draw a line of width @var{n}
-whose top and bottom parts occupy the space of the underlying text,
-thus avoiding any increase in the character height.
+@item @code{(:line-width (@var{vwidth} . @var{hwidth}) :color @var{color} :style @var{style})}
+This way you can explicitly specify all aspects of the box.  The values
+@var{vwidth} and @var{hwidth} specifies respectively the width of the
+vertical and horizontal lines to draw; they default to (1 . 1).
+A negative horizontal or vertical width @minus{}@var{n} means to draw a line
+of width @var{n} that occupies the space of the underlying text, thus
+avoiding any increase in the character height or width. For simplification
+the width could be specified with only a single number @var{n} instead
+of a list, such case is equivalent to @code{((abs @var{n}) . @var{n})}.
 
 The value @var{color} specifies the color to draw with.  The default is
 the foreground color of the face for simple boxes, and the background
diff --git a/lisp/cus-face.el b/lisp/cus-face.el
index 0ee6a8dcc8..aac46da531 100644
--- a/lisp/cus-face.el
+++ b/lisp/cus-face.el
@@ -166,9 +166,11 @@ custom-face-attributes
 	     :help-echo "Control box around text."
 	     (const :tag "Off" nil)
 	     (list :tag "Box"
-		   :value (:line-width 2 :color "grey75" :style released-button)
-		   (const :format "" :value :line-width)
-		   (integer :tag "Width")
+		   :value (:line-width (2 . 2) :color "grey75" :style released-button)
+                   (const :format "" :value :line-width)
+                   (cons :tag "Width" :extra-offset 2
+		    (integer :tag "Vertical")
+		    (integer :tag "Horizontal"))
 		   (const :format "" :value :color)
 		   (choice :tag "Color" (const :tag "*" nil) color)
 		   (const :format "" :value :style)
@@ -181,15 +183,19 @@ custom-face-attributes
        (and real-value
 	    (let ((lwidth
 		   (or (and (consp real-value)
-			    (plist-get real-value :line-width))
+                            (if (listp (cdr real-value))
+			        (plist-get real-value :line-width)
+                              real-value))
 		       (and (integerp real-value) real-value)
-		       1))
+		       '(1 . 1)))
 		  (color
 		   (or (and (consp real-value) (plist-get real-value :color))
 		       (and (stringp real-value) real-value)
 		       nil))
 		  (style
 		   (and (consp real-value) (plist-get real-value :style))))
+              (if (integerp lwidth)
+                  (setq lwidth (cons (abs lwidth) lwidth)))
 	      (list :line-width lwidth :color color :style style))))
      ;; filter to make customized-value suitable for storing
      (lambda (cus-value)
diff --git a/src/dispextern.h b/src/dispextern.h
index 4e947daa25..2d5ab62806 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1648,12 +1648,17 @@ #define FONT_TOO_HIGH(ft)						\
   int fontset;
 
   /* Non-zero means characters in this face have a box of that
-     thickness around them.  If this value is negative, its absolute
-     value indicates the thickness, and the horizontal (top and
-     bottom) borders of box are drawn inside of the character glyphs'
-     area.  The vertical (left and right) borders of the box are drawn
-     in the same way as when this value is positive.  */
-  int box_line_width;
+     thickness around them. Vertical (left and right) and horizontal
+     (top and bottom) borders size can be set separatedly using an
+     associated list of two ints in the form
+     (vertical_size . horizontal_size). In case one of the value is
+     negative, its absolute value indicates the thickness, and the
+     borders of box are drawn inside of the character glyphs' area
+     potentially over the glyph itself but the glyph drawing size is
+     not increase. If a (signed) int N is use instead of a list, it
+     is the same as setting ( abs(N) . N ) values. */
+  int box_vertical_line_width;
+  int box_horizontal_line_width;
 
   /* Type of box drawn.  A value of FACE_NO_BOX means no box is drawn
      around text in this face.  A value of FACE_SIMPLE_BOX means a box
diff --git a/src/nsfont.m b/src/nsfont.m
index 7a40d672b5..0cc9f49705 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -1043,7 +1043,7 @@ is false when (FROM > 0 || TO < S->nchars).  */
 
   r.origin.x = s->x;
   if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p)
-    r.origin.x += abs (s->face->box_line_width);
+    r.origin.x += max (s->face->box_vertical_line_width, 0);
 
   r.origin.y = s->y;
   r.size.height = FONT_HEIGHT (font);
@@ -1105,7 +1105,7 @@ is false when (FROM > 0 || TO < S->nchars).  */
     {
       NSRect br = r;
       int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
-      int mbox_line_width = max (s->face->box_line_width, 0);
+      int mbox_line_width = max (s->face->box_vertical_line_width, 0);
 
       if (s->row->full_width_p)
         {
@@ -1129,9 +1129,10 @@ is false when (FROM > 0 || TO < S->nchars).  */
         }
       else
         {
-          int correction = abs (s->face->box_line_width)+1;
+          int correction = abs (s->face->box_horizontal_line_width)+1;
           br.origin.y += correction;
           br.size.height -= 2*correction;
+          correction = abs (s->face->box_vertical_line_width)+1;
           br.origin.x += correction;
           br.size.width -= 2*correction;
         }
diff --git a/src/nsterm.m b/src/nsterm.m
index 42ef4dd010..237ddc5247 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3530,8 +3530,8 @@ larger if there are taller display elements (e.g., characters
 }
 
 static void
-ns_draw_box (NSRect r, CGFloat thickness, NSColor *col,
-             char left_p, char right_p)
+ns_draw_box (NSRect r, CGFloat hthickness, CGFloat vthickness,
+             NSColor *col, char left_p, char right_p)
 /* --------------------------------------------------------------------------
     Draw an unfilled rect inside r, optionally leaving left and/or right open.
     Note we can't just use an NSDrawRect command, because of the possibility
@@ -3542,28 +3542,28 @@ larger if there are taller display elements (e.g., characters
   [col set];
 
   /* top, bottom */
-  s.size.height = thickness;
+  s.size.height = hthickness;
   NSRectFill (s);
-  s.origin.y += r.size.height - thickness;
+  s.origin.y += r.size.height - hthickness;
   NSRectFill (s);
 
   s.size.height = r.size.height;
   s.origin.y = r.origin.y;
 
   /* left, right (optional) */
-  s.size.width = thickness;
+  s.size.width = vthickness;
   if (left_p)
     NSRectFill (s);
   if (right_p)
     {
-      s.origin.x += r.size.width - thickness;
+      s.origin.x += r.size.width - vthickness;
       NSRectFill (s);
     }
 }
 
 
 static void
-ns_draw_relief (NSRect r, int thickness, char raised_p,
+ns_draw_relief (NSRect r, int hthickness, int vthickness, char raised_p,
                char top_p, char bottom_p, char left_p, char right_p,
                struct glyph_string *s)
 /* --------------------------------------------------------------------------
@@ -3613,27 +3613,27 @@ larger if there are taller display elements (e.g., characters
   /* TODO: mitering. Using NSBezierPath doesn't work because of color switch.  */
 
   /* top */
-  sr.size.height = thickness;
+  sr.size.height = hthickness;
   if (top_p) NSRectFill (sr);
 
   /* left */
   sr.size.height = r.size.height;
-  sr.size.width = thickness;
+  sr.size.width = vthickness;
   if (left_p) NSRectFill (sr);
 
   [(raised_p ? darkCol : lightCol) set];
 
   /* bottom */
   sr.size.width = r.size.width;
-  sr.size.height = thickness;
-  sr.origin.y += r.size.height - thickness;
+  sr.size.height = hthickness;
+  sr.origin.y += r.size.height - hthickness;
   if (bottom_p) NSRectFill (sr);
 
   /* right */
   sr.size.height = r.size.height;
   sr.origin.y = r.origin.y;
-  sr.size.width = thickness;
-  sr.origin.x += r.size.width - thickness;
+  sr.size.width = vthickness;
+  sr.origin.x += r.size.width - vthickness;
   if (right_p) NSRectFill (sr);
 }
 
@@ -3649,7 +3649,7 @@ Function modeled after x_draw_glyph_string_box ().
   char left_p, right_p;
   struct glyph *last_glyph;
   NSRect r;
-  int thickness;
+  int hthickness, vthickness;
   struct face *face;
 
   if (s->hl == DRAW_MOUSE_FACE)
@@ -3662,7 +3662,8 @@ Function modeled after x_draw_glyph_string_box ().
   else
     face = s->face;
 
-  thickness = face->box_line_width;
+  vthickness = face->box_vertical_line_width;
+  hthickness = face->box_horizontal_line_width;
 
   NSTRACE ("ns_dumpglyphs_box_or_relief");
 
@@ -3687,14 +3688,15 @@ Function modeled after x_draw_glyph_string_box ().
   /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate.  */
   if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
     {
-      ns_draw_box (r, abs (thickness),
+      ns_draw_box (r, abs (hthickness), abs (vthickness),
                    ns_lookup_indexed_color (face->box_color, s->f),
-                  left_p, right_p);
+                   left_p, right_p);
     }
   else
     {
-      ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
-                     1, 1, left_p, right_p, s);
+      ns_draw_relief (r, abs (hthickness), abs (vthickness),
+                      s->face->box == FACE_RAISED_BOX,
+                      1, 1, left_p, right_p, s);
     }
 }
 
@@ -3710,7 +3712,7 @@ Function modeled after x_draw_glyph_string_box ().
 
   if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
     {
-      int box_line_width = max (s->face->box_line_width, 0);
+      int box_line_width = max (s->face->box_horizontal_line_width, 0);
       if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
 	  /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
 	     dimensions, since the actual glyphs might be much
@@ -3761,7 +3763,7 @@ Function modeled after x_draw_glyph_string_box ().
    -------------------------------------------------------------------------- */
 {
   EmacsImage *img = s->img->pixmap;
-  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
   int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
   int bg_x, bg_y, bg_height;
   int th;
@@ -3774,7 +3776,7 @@ Function modeled after x_draw_glyph_string_box ().
 
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   bg_x = x;
   bg_y =  s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
@@ -3887,7 +3889,7 @@ Function modeled after x_draw_glyph_string_box ().
       r.origin.y = y - th;
       r.size.width = s->slice.width + 2*th-1;
       r.size.height = s->slice.height + 2*th-1;
-      ns_draw_relief (r, th, raised_p,
+      ns_draw_relief (r, th, th, raised_p,
                       s->slice.y == 0,
                       s->slice.y + s->slice.height == s->img->height,
                       s->slice.x == 0,
@@ -3901,7 +3903,7 @@ Function modeled after x_draw_glyph_string_box ().
     {
       int thickness = abs (s->img->relief);
       if (thickness == 0) thickness = 1;
-      ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
+      ns_draw_box (br, thickness, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
     }
 }
 
@@ -4008,7 +4010,7 @@ overwriting cursor (usually when cursor on a tab).  */
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -4034,7 +4036,7 @@ overwriting cursor (usually when cursor on a tab).  */
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -4050,7 +4052,7 @@ overwriting cursor (usually when cursor on a tab).  */
       if (s->cmp_from == 0)
         {
           NSRect r = NSMakeRect (s->x, s->y, s->width-1, s->height -1);
-          ns_draw_box (r, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
+          ns_draw_box (r, 1, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
         }
     }
   else if (! s->first_glyph->u.cmp.automatic)
diff --git a/src/w32term.c b/src/w32term.c
index ad96287a43..24d21897ff 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -884,10 +884,10 @@ w32_destroy_fringe_bitmap (int which)
 static void w32_clear_glyph_string_rect (struct glyph_string *, int,
                                          int, int, int);
 static void w32_draw_relief_rect (struct frame *, int, int, int, int,
-                                  int, int, int, int, int, int,
+                                  int, int, int, int, int, int, int,
                                   RECT *);
 static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
-                               int, bool, bool, RECT *);
+                               int, int, bool, bool, RECT *);
 
 
 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
@@ -1156,7 +1156,7 @@ w32_draw_glyph_string_background (struct glyph_string *s, bool force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
-      int box_line_width = max (s->face->box_line_width, 0);
+      int box_line_width = max (s->face->box_horizontal_line_width, 0);
 
 #if 0 /* TODO: stipple */
       if (s->stippled_p)
@@ -1202,7 +1202,7 @@ w32_draw_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1260,7 +1260,7 @@ w32_draw_composite_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1357,7 +1357,7 @@ w32_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1613,7 +1613,7 @@ w32_setup_relief_colors (struct glyph_string *s)
 static void
 w32_draw_relief_rect (struct frame *f,
 		      int left_x, int top_y, int right_x, int bottom_y,
-		      int width, int raised_p,
+		      int hwidth, int vwidth, int raised_p,
 		      int top_p, int bot_p, int left_p, int right_p,
 		      RECT *clip_rect)
 {
@@ -1630,14 +1630,14 @@ w32_draw_relief_rect (struct frame *f,
 
   /* Top.  */
   if (top_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < hwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     left_x + i * left_p, top_y + i,
 		     right_x - left_x - i * (left_p + right_p ) + 1, 1);
 
   /* Left.  */
   if (left_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < vwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     left_x + i, top_y + (i + 1) * top_p, 1,
 		     bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@@ -1649,14 +1649,14 @@ w32_draw_relief_rect (struct frame *f,
 
   /* Bottom.  */
   if (bot_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < hwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     left_x + i * left_p, bottom_y - i,
 		     right_x - left_x - i * (left_p + right_p) + 1, 1);
 
   /* Right.  */
   if (right_p)
-    for (i = 0; i < width; ++i)
+    for (i = 0; i < vwidth; ++i)
       w32_fill_area (f, hdc, gc.foreground,
 		     right_x - i, top_y + (i + 1) * top_p, 1,
 		     bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@@ -1676,31 +1676,31 @@ w32_draw_relief_rect (struct frame *f,
 
 static void
 w32_draw_box_rect (struct glyph_string *s,
-		   int left_x, int top_y, int right_x, int bottom_y, int width,
-                   bool left_p, bool right_p, RECT *clip_rect)
+		   int left_x, int top_y, int right_x, int bottom_y, int hwidth,
+		   int vwidth, bool left_p, bool right_p, RECT *clip_rect)
 {
   w32_set_clip_rectangle (s->hdc, clip_rect);
 
   /* Top.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
-		  left_x, top_y, right_x - left_x + 1, width);
+		  left_x, top_y, right_x - left_x + 1, hwidth);
 
   /* Left.  */
   if (left_p)
     {
       w32_fill_area (s->f, s->hdc, s->face->box_color,
-                     left_x, top_y, width, bottom_y - top_y + 1);
+                     left_x, top_y, vwidth, bottom_y - top_y + 1);
     }
 
   /* Bottom.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
-                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+                 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
 
   /* Right.  */
   if (right_p)
     {
       w32_fill_area (s->f, s->hdc, s->face->box_color,
-                     right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+                     right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
     }
 
   w32_set_clip_rectangle (s->hdc, NULL);
@@ -1712,7 +1712,7 @@ w32_draw_box_rect (struct glyph_string *s,
 static void
 w32_draw_glyph_string_box (struct glyph_string *s)
 {
-  int width, left_x, right_x, top_y, bottom_y, last_x;
+  int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
   bool left_p, right_p, raised_p;
   struct glyph *last_glyph;
   RECT clip_rect;
@@ -1726,7 +1726,8 @@ w32_draw_glyph_string_box (struct glyph_string *s)
 		? s->first_glyph
 		: s->first_glyph + s->nchars - 1);
 
-  width = eabs (s->face->box_line_width);
+  vwidth = eabs (s->face->box_vertical_line_width);
+  hwidth = eabs (s->face->box_horizontal_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
   right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
@@ -1747,13 +1748,13 @@ w32_draw_glyph_string_box (struct glyph_string *s)
   get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
-    w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
-                       left_p, right_p, &clip_rect);
+    w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
+                       vwidth, left_p, right_p, &clip_rect);
   else
     {
       w32_setup_relief_colors (s);
-      w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-                            width, raised_p, 1, 1, left_p, right_p, &clip_rect);
+      w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
+                            vwidth, raised_p, 1, 1, left_p, right_p, &clip_rect);
     }
 }
 
@@ -1791,7 +1792,7 @@ w32_draw_image_foreground (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -1978,7 +1979,7 @@ w32_draw_image_relief (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2030,7 +2031,7 @@ w32_draw_image_relief (struct glyph_string *s)
 
   w32_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  w32_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
+  w32_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
 			top_p, bot_p, left_p, right_p, &r);
 }
 
@@ -2050,7 +2051,7 @@ w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2163,8 +2164,8 @@ w32_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int
 w32_draw_image_glyph_string (struct glyph_string *s)
 {
   int x, y;
-  int box_line_hwidth = eabs (s->face->box_line_width);
-  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
+  int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
   int height, width;
   HBITMAP pixmap = 0;
 
diff --git a/src/xdisp.c b/src/xdisp.c
index 7338d2b7d4..b2cae1131f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1937,8 +1937,8 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
 	    {
 	      if (face->font)
 		height = normal_char_height (face->font, -1);
-	      if (face->box_line_width > 0)
-		height += 2 * face->box_line_width;
+	      if (face->box_horizontal_line_width > 0)
+		height += 2 * face->box_horizontal_line_width;
 	    }
 	}
 
@@ -27605,18 +27605,21 @@ produce_image_glyph (struct it *it)
 
   if (face->box != FACE_NO_BOX)
     {
-      if (face->box_line_width > 0)
+      if (face->box_horizontal_line_width > 0)
 	{
 	  if (slice.y == 0)
-	    it->ascent += face->box_line_width;
+	    it->ascent += face->box_horizontal_line_width;
 	  if (slice.y + slice.height == img->height)
-	    it->descent += face->box_line_width;
+	    it->descent += face->box_horizontal_line_width;
 	}
 
-      if (it->start_of_box_run_p && slice.x == 0)
-	it->pixel_width += eabs (face->box_line_width);
-      if (it->end_of_box_run_p && slice.x + slice.width == img->width)
-	it->pixel_width += eabs (face->box_line_width);
+      if (face->box_vertical_line_width > 0)
+	{
+	  if (it->start_of_box_run_p && slice.x == 0)
+	    it->pixel_width += face->box_vertical_line_width;
+	  if (it->end_of_box_run_p && slice.x + slice.width == img->width)
+	    it->pixel_width += face->box_vertical_line_width;
+	}
     }
 
   take_vertical_position_into_account (it);
@@ -27714,15 +27717,18 @@ produce_xwidget_glyph (struct it *it)
 
   if (face->box != FACE_NO_BOX)
     {
-      if (face->box_line_width > 0)
+      if (face->box_horizontal_line_width > 0)
 	{
-	  it->ascent += face->box_line_width;
-	  it->descent += face->box_line_width;
+	  it->ascent += face->box_horizontal_line_width;
+	  it->descent += face->box_horizontal_line_width;
 	}
 
-      if (it->start_of_box_run_p)
-	it->pixel_width += eabs (face->box_line_width);
-      it->pixel_width += eabs (face->box_line_width);
+      if (face->box_vertical_line_width > 0)
+	{
+	  if (it->start_of_box_run_p)
+	    it->pixel_width += face->box_vertical_line_width;
+	  it->pixel_width += face->box_vertical_line_width;
+	}
     }
 
   take_vertical_position_into_account (it);
@@ -28485,6 +28491,31 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
 }
 
 
+/* If face has a box, add the box thickness to the character
+   height.  If character has a box line to the left and/or
+   right, add the box line width to the character's width.  */
+#define IT_APPLY_FACE_BOX(it, face)				\
+  do {								\
+    if (face->box != FACE_NO_BOX)				\
+      {								\
+	int thick = face->box_horizontal_line_width;		\
+	if (thick > 0)						\
+	  {							\
+	    it->ascent += thick;				\
+	    it->descent += thick;				\
+	  }							\
+								\
+	thick = face->box_vertical_line_width;			\
+	if (thick > 0)						\
+	  {							\
+	    if (it->start_of_box_run_p)				\
+	      it->pixel_width += thick;				\
+	    if (it->end_of_box_run_p)				\
+	      it->pixel_width += thick;				\
+	  }							\
+      }								\
+    } while (false)
+
 /* RIF:
    Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct it in dispextern.h
@@ -28600,26 +28631,7 @@ gui_produce_glyphs (struct it *it)
 	  if (stretched_p)
 	    it->pixel_width *= XFLOATINT (it->space_width);
 
-	  /* If face has a box, add the box thickness to the character
-	     height.  If character has a box line to the left and/or
-	     right, add the box line width to the character's width.  */
-	  if (face->box != FACE_NO_BOX)
-	    {
-	      int thick = face->box_line_width;
-
-	      if (thick > 0)
-		{
-		  it->ascent += thick;
-		  it->descent += thick;
-		}
-	      else
-		thick = -thick;
-
-	      if (it->start_of_box_run_p)
-		it->pixel_width += thick;
-	      if (it->end_of_box_run_p)
-		it->pixel_width += thick;
-	    }
+	  IT_APPLY_FACE_BOX(it, face);
 
 	  /* If face has an overline, add the height of the overline
 	     (1 pixel) and a 1 pixel margin to the character height.  */
@@ -28734,10 +28746,10 @@ gui_produce_glyphs (struct it *it)
 
 	      if ((it->max_ascent > 0 || it->max_descent > 0)
 		  && face->box != FACE_NO_BOX
-		  && face->box_line_width > 0)
+		  && face->box_horizontal_line_width > 0)
 		{
-		  it->ascent += face->box_line_width;
-		  it->descent += face->box_line_width;
+		  it->ascent += face->box_horizontal_line_width;
+		  it->descent += face->box_horizontal_line_width;
 		}
 	      if (!NILP (height)
 		  && XFIXNUM (height) > it->ascent + it->descent)
@@ -29144,23 +29156,7 @@ gui_produce_glyphs (struct it *it)
       it->pixel_width = cmp->pixel_width;
       it->ascent = it->phys_ascent = cmp->ascent;
       it->descent = it->phys_descent = cmp->descent;
-      if (face->box != FACE_NO_BOX)
-	{
-	  int thick = face->box_line_width;
-
-	  if (thick > 0)
-	    {
-	      it->ascent += thick;
-	      it->descent += thick;
-	    }
-	  else
-	    thick = - thick;
-
-	  if (it->start_of_box_run_p)
-	    it->pixel_width += thick;
-	  if (it->end_of_box_run_p)
-	    it->pixel_width += thick;
-	}
+      IT_APPLY_FACE_BOX(it, face);
 
       /* If face has an overline, add the height of the overline
 	 (1 pixel) and a 1 pixel margin to the character height.  */
@@ -29194,23 +29190,8 @@ gui_produce_glyphs (struct it *it)
 	it->glyph_row->contains_overlapping_glyphs_p = true;
       it->ascent = it->phys_ascent = metrics.ascent;
       it->descent = it->phys_descent = metrics.descent;
-      if (face->box != FACE_NO_BOX)
-	{
-	  int thick = face->box_line_width;
+      IT_APPLY_FACE_BOX(it, face);
 
-	  if (thick > 0)
-	    {
-	      it->ascent += thick;
-	      it->descent += thick;
-	    }
-	  else
-	    thick = - thick;
-
-	  if (it->start_of_box_run_p)
-	    it->pixel_width += thick;
-	  if (it->end_of_box_run_p)
-	    it->pixel_width += thick;
-	}
       /* If face has an overline, add the height of the overline
 	 (1 pixel) and a 1 pixel margin to the character height.  */
       if (face->overline_p)
diff --git a/src/xfaces.c b/src/xfaces.c
index c3cae7e2a6..e5f6275d64 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2972,6 +2972,8 @@ DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
 	valid_p = XFIXNUM (value) != 0;
       else if (STRINGP (value))
 	valid_p = SCHARS (value) > 0;
+      else if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value)))
+	valid_p = true;
       else if (CONSP (value))
 	{
 	  Lisp_Object tem;
@@ -2990,7 +2992,9 @@ DEFUN ("internal-set-lisp-face-attribute", Finternal_set_lisp_face_attribute,
 
 	      if (EQ (k, QCline_width))
 		{
-		  if (!FIXNUMP (v) || XFIXNUM (v) == 0)
+		  if ((!CONSP(v) || !FIXNUMP (XCAR (v)) || XFIXNUM (XCAR (v)) == 0
+		                 || !FIXNUMP (XCDR (v)) || XFIXNUM (XCDR (v)) == 0)
+		      && (!FIXNUMP (v) || XFIXNUM (v) == 0))
 		    break;
 		}
 	      else if (EQ (k, QCcolor))
@@ -5631,7 +5635,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
       face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
 				    LFACE_BOX_INDEX);
       face->box = FACE_SIMPLE_BOX;
-      face->box_line_width = 1;
+      face->box_vertical_line_width = face->box_horizontal_line_width = 1;
     }
   else if (FIXNUMP (box))
     {
@@ -5639,9 +5643,19 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
 	 face.  */
       eassert (XFIXNUM (box) != 0);
       face->box = FACE_SIMPLE_BOX;
-      face->box_line_width = XFIXNUM (box);
+      face->box_vertical_line_width = eabs(XFIXNUM (box));
+      face->box_horizontal_line_width = XFIXNUM (box);
+      face->box_color = face->foreground;
+      face->box_color_defaulted_p = true;
+    }
+  else if (CONSP (box) && FIXNUMP (XCAR (box)) && FIXNUMP (XCDR (box)))
+    {
+	/* `(VWIDTH . HWIDTH)'.  */
+      face->box = FACE_SIMPLE_BOX;
       face->box_color = face->foreground;
       face->box_color_defaulted_p = true;
+      face->box_vertical_line_width = XFIXNUM (XCAR (box));
+      face->box_horizontal_line_width = XFIXNUM (XCDR (box));
     }
   else if (CONSP (box))
     {
@@ -5650,7 +5664,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
       face->box = FACE_SIMPLE_BOX;
       face->box_color = face->foreground;
       face->box_color_defaulted_p = true;
-      face->box_line_width = 1;
+      face->box_vertical_line_width = face->box_horizontal_line_width = 1;
 
       while (CONSP (box))
 	{
@@ -5666,8 +5680,14 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
 
 	  if (EQ (keyword, QCline_width))
 	    {
-	      if (FIXNUMP (value) && XFIXNUM (value) != 0)
-		face->box_line_width = XFIXNUM (value);
+	      if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value))) {
+		  face->box_vertical_line_width = XFIXNUM (XCAR (value));
+		  face->box_horizontal_line_width = XFIXNUM (XCDR (value));
+	      }
+	      else if (FIXNUMP (value) && XFIXNUM (value) != 0) {
+		face->box_vertical_line_width = eabs (XFIXNUM (value));
+		face->box_horizontal_line_width = XFIXNUM (value);
+	      }
 	    }
 	  else if (EQ (keyword, QCcolor))
 	    {
diff --git a/src/xterm.c b/src/xterm.c
index bbe68ef622..3cc35dcbd8 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1754,7 +1754,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
-      int box_line_width = max (s->face->box_line_width, 0);
+      int box_line_width = max (s->face->box_horizontal_line_width, 0);
 
       if (s->stippled_p)
 	{
@@ -1799,7 +1799,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -1849,7 +1849,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
 	  if (!(s->for_overlaps
 		|| (s->background_filled_p && s->hl != DRAW_CURSOR)))
 	    {
-	      int box_line_width = max (s->face->box_line_width, 0);
+	      int box_line_width = max (s->face->box_horizontal_line_width, 0);
 
 	      if (s->stippled_p)
 		{
@@ -1893,7 +1893,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -2004,7 +2004,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
      of S to the right of that box line.  */
   if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + eabs (s->face->box_line_width);
+    x = s->x + max (s->face->box_vertical_line_width, 0);
   else
     x = s->x;
 
@@ -2770,7 +2770,7 @@ x_setup_relief_colors (struct glyph_string *s)
 static void
 x_draw_relief_rect (struct frame *f,
 		    int left_x, int top_y, int right_x, int bottom_y,
-		    int width, bool raised_p, bool top_p, bool bot_p,
+		    int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
 		    bool left_p, bool right_p,
 		    XRectangle *clip_rect)
 {
@@ -2795,7 +2795,7 @@ x_draw_relief_rect (struct frame *f,
   if (left_p)
     {
       x_fill_rectangle (f, top_left_gc, left_x, top_y,
-			width, bottom_y + 1 - top_y);
+			vwidth, bottom_y + 1 - top_y);
       if (top_p)
 	corners |= 1 << CORNER_TOP_LEFT;
       if (bot_p)
@@ -2803,8 +2803,8 @@ x_draw_relief_rect (struct frame *f,
     }
   if (right_p)
     {
-      x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
-			width, bottom_y + 1 - top_y);
+      x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
+			vwidth, bottom_y + 1 - top_y);
       if (top_p)
 	corners |= 1 << CORNER_TOP_RIGHT;
       if (bot_p)
@@ -2814,25 +2814,25 @@ x_draw_relief_rect (struct frame *f,
     {
       if (!right_p)
 	x_fill_rectangle (f, top_left_gc, left_x, top_y,
-			  right_x + 1 - left_x, width);
+			  right_x + 1 - left_x, hwidth);
       else
 	x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
-				     right_x + 1 - left_x, width, 1);
+				     right_x + 1 - left_x, hwidth, 1);
     }
   if (bot_p)
     {
       if (!left_p)
-	x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
-			  right_x + 1 - left_x, width);
+	x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
+			  right_x + 1 - left_x, hwidth);
       else
 	x_fill_trapezoid_for_relief (f, bottom_right_gc,
-				     left_x, bottom_y + 1 - width,
-				     right_x + 1 - left_x, width, 0);
+				     left_x, bottom_y + 1 - hwidth,
+				     right_x + 1 - left_x, hwidth, 0);
     }
-  if (left_p && width != 1)
+  if (left_p && vwidth > 1)
     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
 		      1, bottom_y + 1 - top_y);
-  if (top_p && width != 1)
+  if (top_p && hwidth > 1)
     x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
 		      right_x + 1 - left_x, 1);
   if (corners)
@@ -2866,12 +2866,12 @@ x_draw_relief_rect (struct frame *f,
   /* Top.  */
   if (top_p)
     {
-      if (width == 1)
+      if (hwidth == 1)
         XDrawLine (dpy, drawable, gc,
 		   left_x + left_p, top_y,
 		   right_x + !right_p, top_y);
 
-      for (i = 1; i < width; ++i)
+      for (i = 1; i < hwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   left_x  + i * left_p, top_y + i,
 		   right_x + 1 - i * right_p, top_y + i);
@@ -2880,13 +2880,10 @@ x_draw_relief_rect (struct frame *f,
   /* Left.  */
   if (left_p)
     {
-      if (width == 1)
+      if (vwidth == 1)
         XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
 
-      x_clear_area(f, left_x, top_y, 1, 1);
-      x_clear_area(f, left_x, bottom_y, 1, 1);
-
-      for (i = (width > 1 ? 1 : 0); i < width; ++i)
+      for (i = 1; i < vwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   left_x + i, top_y + (i + 1) * top_p,
 		   left_x + i, bottom_y + 1 - (i + 1) * bot_p);
@@ -2899,26 +2896,25 @@ x_draw_relief_rect (struct frame *f,
     gc = f->output_data.x->white_relief.gc;
   XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
 
-  if (width > 1)
-    {
-      /* Outermost top line.  */
-      if (top_p)
-        XDrawLine (dpy, drawable, gc,
-		   left_x  + left_p, top_y,
-		   right_x + !right_p, top_y);
+  /* Outermost top line.  */
+  if (top_p && hwidth > 1)
+    XDrawLine (dpy, drawable, gc,
+	       left_x  + left_p, top_y,
+	       right_x + !right_p, top_y);
 
-      /* Outermost left line.  */
-      if (left_p)
-        XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
-    }
+  /* Outermost left line.  */
+  if (left_p && vwidth > 1)
+    XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
 
   /* Bottom.  */
   if (bot_p)
     {
-      XDrawLine (dpy, drawable, gc,
-		 left_x + left_p, bottom_y,
-		 right_x + !right_p, bottom_y);
-      for (i = 1; i < width; ++i)
+      if (hwidth >= 1)
+        XDrawLine (dpy, drawable, gc,
+		   left_x + left_p, bottom_y,
+		   right_x + !right_p, bottom_y);
+
+      for (i = 1; i < hwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   left_x  + i * left_p, bottom_y - i,
 		   right_x + 1 - i * right_p, bottom_y - i);
@@ -2927,9 +2923,7 @@ x_draw_relief_rect (struct frame *f,
   /* Right.  */
   if (right_p)
     {
-      x_clear_area(f, right_x, top_y, 1, 1);
-      x_clear_area(f, right_x, bottom_y, 1, 1);
-      for (i = 0; i < width; ++i)
+      for (i = 0; i < vwidth; ++i)
         XDrawLine (dpy, drawable, gc,
 		   right_x - i, top_y + (i + 1) * top_p,
 		   right_x - i, bottom_y + 1 - (i + 1) * bot_p);
@@ -2950,8 +2944,8 @@ x_draw_relief_rect (struct frame *f,
 
 static void
 x_draw_box_rect (struct glyph_string *s,
-		 int left_x, int top_y, int right_x, int bottom_y, int width,
-		 bool left_p, bool right_p, XRectangle *clip_rect)
+		 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
+		 int vwidth, bool left_p, bool right_p, XRectangle *clip_rect)
 {
   Display *display = FRAME_X_DISPLAY (s->f);
   XGCValues xgcv;
@@ -2962,21 +2956,21 @@ x_draw_box_rect (struct glyph_string *s,
 
   /* Top.  */
   x_fill_rectangle (s->f, s->gc,
-		  left_x, top_y, right_x - left_x + 1, width);
+		  left_x, top_y, right_x - left_x + 1, hwidth);
 
   /* Left.  */
   if (left_p)
     x_fill_rectangle (s->f, s->gc,
-		    left_x, top_y, width, bottom_y - top_y + 1);
+		    left_x, top_y, vwidth, bottom_y - top_y + 1);
 
   /* Bottom.  */
   x_fill_rectangle (s->f, s->gc,
-		  left_x, bottom_y - width + 1, right_x - left_x + 1, width);
+		  left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
 
   /* Right.  */
   if (right_p)
     x_fill_rectangle (s->f, s->gc,
-		    right_x - width + 1, top_y, width, bottom_y - top_y + 1);
+		    right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
 
   XSetForeground (display, s->gc, xgcv.foreground);
   x_reset_clip_rectangles (s->f, s->gc);
@@ -2988,7 +2982,7 @@ x_draw_box_rect (struct glyph_string *s,
 static void
 x_draw_glyph_string_box (struct glyph_string *s)
 {
-  int width, left_x, right_x, top_y, bottom_y, last_x;
+  int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
   bool raised_p, left_p, right_p;
   struct glyph *last_glyph;
   XRectangle clip_rect;
@@ -3002,7 +2996,8 @@ x_draw_glyph_string_box (struct glyph_string *s)
 		? s->first_glyph
 		: s->first_glyph + s->nchars - 1);
 
-  width = eabs (s->face->box_line_width);
+  vwidth = eabs (s->face->box_vertical_line_width);
+  hwidth = eabs (s->face->box_horizontal_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
   right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
@@ -3023,13 +3018,13 @@ x_draw_glyph_string_box (struct glyph_string *s)
   get_glyph_string_clip_rect (s, &clip_rect);
 
   if (s->face->box == FACE_SIMPLE_BOX)
-    x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
-		     left_p, right_p, &clip_rect);
+    x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
+		     vwidth, left_p, right_p, &clip_rect);
   else
     {
       x_setup_relief_colors (s);
-      x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
-			  width, raised_p, true, true, left_p, right_p,
+      x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
+			  vwidth, raised_p, true, true, left_p, right_p,
 			  &clip_rect);
     }
 }
@@ -3089,7 +3084,7 @@ x_draw_image_foreground (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -3208,7 +3203,7 @@ x_draw_image_relief (struct glyph_string *s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -3261,7 +3256,7 @@ x_draw_image_relief (struct glyph_string *s)
 
   x_setup_relief_colors (s);
   get_glyph_string_clip_rect (s, &r);
-  x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p,
+  x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
 		      top_p, bot_p, left_p, right_p, &r);
 }
 
@@ -3280,7 +3275,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += eabs (s->face->box_line_width);
+    x += max (s->face->box_vertical_line_width, 0);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -3381,8 +3376,8 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
 static void
 x_draw_image_glyph_string (struct glyph_string *s)
 {
-  int box_line_hwidth = eabs (s->face->box_line_width);
-  int box_line_vwidth = max (s->face->box_line_width, 0);
+  int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
+  int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
   int height;
 #ifndef USE_CAIRO
   Display *display = FRAME_X_DISPLAY (s->f);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#13011: [PATCH] Text flickering moving cursor with box around text enabled
  2019-08-10 21:21 ` bug#13011: [PATCH] " Alexandre Adolphe
@ 2019-08-20 13:44   ` Noam Postavsky
  2019-10-11 23:31     ` Alexandre Adolphe
  2019-10-15  7:40     ` Stefan Kangas
  2020-04-01 22:05   ` Noam Postavsky
  2020-04-03  1:27   ` Dmitry Gutov
  2 siblings, 2 replies; 28+ messages in thread
From: Noam Postavsky @ 2019-08-20 13:44 UTC (permalink / raw)
  To: Alexandre Adolphe; +Cc: 13011

Alexandre Adolphe <alexandre.adolphe@gmail.com> writes:

> After seeing that some people were interrest about this issue on reddit, I
> rejump in this change. I saw that the customization of box were not
> correctly done so I correct it.
> Here is the updated patch.

It looks okay I think (I don't run macOS either though).  Have you
assigned copyright?  I don't see your name in the list.

If you are willing to assign copyright, you can get that started by
filling in the form at
https://git.savannah.gnu.org/cgit/gnulib.git/tree/doc/Copyright/request-assign.future
and sending it to assign@gnu.org.  The clerk will reply with further
instructions.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: [PATCH] Text flickering moving cursor with box around text enabled
  2019-08-20 13:44   ` Noam Postavsky
@ 2019-10-11 23:31     ` Alexandre Adolphe
  2019-10-15  7:40     ` Stefan Kangas
  1 sibling, 0 replies; 28+ messages in thread
From: Alexandre Adolphe @ 2019-10-11 23:31 UTC (permalink / raw)
  To: Noam Postavsky; +Cc: 13011

Hi Noam,

Le mar. 20 août 2019 à 15:44, Noam Postavsky <npostavs@gmail.com> a écrit :
>
> It looks okay I think (I don't run macOS either though).  Have you
> assigned copyright?  I don't see your name in the list.

I have completed the assignment for copyright.
I also checked that the patch is always applying correctly.

Thanks in advance,
Alexandre





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: [PATCH] Text flickering moving cursor with box around text enabled
  2019-08-20 13:44   ` Noam Postavsky
  2019-10-11 23:31     ` Alexandre Adolphe
@ 2019-10-15  7:40     ` Stefan Kangas
  1 sibling, 0 replies; 28+ messages in thread
From: Stefan Kangas @ 2019-10-15  7:40 UTC (permalink / raw)
  To: Noam Postavsky; +Cc: Alexandre Adolphe, 13011

Noam Postavsky <npostavs@gmail.com> writes:

> It looks okay I think (I don't run macOS either though).  Have you
> assigned copyright?  I don't see your name in the list.

I've tested the patch on macOS 10.13, and it works as expected.  One
could use this to see that it gets rid of the horizontal flickering
when changing lines:

  (custom-set-variables '(global-hl-line-mode t))
  (custom-set-faces '(hl-line ((t (:box (:line-width (-1 . -1) :color
"gray50"))))))

Best regards,
Stefan Kangas





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: [PATCH] Text flickering moving cursor with box around text enabled
  2019-08-10 21:21 ` bug#13011: [PATCH] " Alexandre Adolphe
  2019-08-20 13:44   ` Noam Postavsky
@ 2020-04-01 22:05   ` Noam Postavsky
  2020-04-03  1:27   ` Dmitry Gutov
  2 siblings, 0 replies; 28+ messages in thread
From: Noam Postavsky @ 2020-04-01 22:05 UTC (permalink / raw)
  To: Alexandre Adolphe; +Cc: 13011

tags 13011 fixed
close 13011 28.1
quit

Alexandre Adolphe <alexandre.adolphe@gmail.com> writes:

> After seeing that some people were interrest about this issue on reddit, I
> rejump in this change. I saw that the customization of box were not
> correctly done so I correct it.
> Here is the updated patch.

Finally pushed to master, sorry for the delay.

[1: 34ae2d0c22]: 2020-04-01 18:02:55 -0400
  Allow negative line width for :box face attribute
  https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=34ae2d0c220c945443e94a43d043a4a63c444bf4





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#13011: [PATCH] Text flickering moving cursor with box around text enabled
  2019-08-10 21:21 ` bug#13011: [PATCH] " Alexandre Adolphe
  2019-08-20 13:44   ` Noam Postavsky
  2020-04-01 22:05   ` Noam Postavsky
@ 2020-04-03  1:27   ` Dmitry Gutov
  2 siblings, 0 replies; 28+ messages in thread
From: Dmitry Gutov @ 2020-04-03  1:27 UTC (permalink / raw)
  To: Alexandre Adolphe, 13011

On 11.08.2019 00:21, Alexandre Adolphe wrote:
> After seeing that some people were interrest about this issue on reddit, 
> I rejump in this change. I saw that the customization of box were not 
> correctly done so I correct it.
> Here is the updated patch.

Thanks, Alexandre!

It's a welcome change.





^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2020-04-03  1:27 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-27 10:42 bug#13011: 24.2; Text flickering moving cursor with box around text enabled mario giovinazzo
2012-11-27 17:43 ` Eli Zaretskii
     [not found]   ` <1205106717.20121128161453@virgilio.it>
2012-11-28 17:54     ` Eli Zaretskii
2012-11-29  4:39       ` Stefan Monnier
2012-11-29 16:42         ` Eli Zaretskii
2012-11-29 19:06           ` Stefan Monnier
2012-12-03  9:29             ` Kenichi Handa
2012-12-03 16:33               ` Eli Zaretskii
2012-12-03 16:44                 ` Drew Adams
2012-12-03 18:08                   ` Eli Zaretskii
2012-12-03 18:41                     ` Drew Adams
2012-12-03 18:56                       ` Eli Zaretskii
2012-12-03 19:09                         ` Drew Adams
2012-12-03 21:04                           ` Eli Zaretskii
2012-12-03 22:20                             ` Stefan Monnier
2012-12-03 22:51                               ` Drew Adams
2012-12-03 22:21                             ` Drew Adams
2012-12-04  0:13                 ` Kenichi Handa
2018-01-19 18:08 ` bug#13011: Patch: " Alexandre Adolphe
2019-08-10 21:21 ` bug#13011: [PATCH] " Alexandre Adolphe
2019-08-20 13:44   ` Noam Postavsky
2019-10-11 23:31     ` Alexandre Adolphe
2019-10-15  7:40     ` Stefan Kangas
2020-04-01 22:05   ` Noam Postavsky
2020-04-03  1:27   ` Dmitry Gutov
     [not found] <13b4ec68081.mario.giovinazzo@virgilio.it>
2012-11-30  8:13 ` bug#13011: 24.2; " Eli Zaretskii
2012-12-11 12:26   ` Eli Zaretskii
2012-12-11 14:01     ` Stefan Monnier

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).