aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrea Corallo2020-04-03 11:15:55 +0100
committerAndrea Corallo2020-04-03 11:15:55 +0100
commit3cc0438629843e7dbd3bda8bbcf6578b2e7f6200 (patch)
tree8ce51634d61a8ebb617454d98ac6047f81da1211 /src
parent63af801ed34c8dc59fb13c9e058c49203a1ae55d (diff)
parentf28166dc9a56111606be8ac50ad38179a66ea636 (diff)
downloademacs-3cc0438629843e7dbd3bda8bbcf6578b2e7f6200.tar.gz
emacs-3cc0438629843e7dbd3bda8bbcf6578b2e7f6200.zip
Merge remote-tracking branch 'savannah/master' into HEAD
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c106
-rw-r--r--src/buffer.c66
-rw-r--r--src/buffer.h12
-rw-r--r--src/decompress.c6
-rw-r--r--src/dispextern.h17
-rw-r--r--src/nsfont.m7
-rw-r--r--src/nsterm.m56
-rw-r--r--src/pdumper.c4
-rw-r--r--src/w32term.c59
-rw-r--r--src/xdisp.c123
-rw-r--r--src/xfaces.c39
-rw-r--r--src/xterm.c115
12 files changed, 265 insertions, 345 deletions
diff --git a/src/alloc.c b/src/alloc.c
index db0646c81e3..147e018095b 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -432,7 +432,6 @@ inline static void set_interval_marked (INTERVAL i);
432enum mem_type 432enum mem_type
433{ 433{
434 MEM_TYPE_NON_LISP, 434 MEM_TYPE_NON_LISP,
435 MEM_TYPE_BUFFER,
436 MEM_TYPE_CONS, 435 MEM_TYPE_CONS,
437 MEM_TYPE_STRING, 436 MEM_TYPE_STRING,
438 MEM_TYPE_SYMBOL, 437 MEM_TYPE_SYMBOL,
@@ -3339,12 +3338,10 @@ allocate_pseudovector (int memlen, int lisplen,
3339struct buffer * 3338struct buffer *
3340allocate_buffer (void) 3339allocate_buffer (void)
3341{ 3340{
3342 struct buffer *b = lisp_malloc (sizeof *b, false, MEM_TYPE_BUFFER); 3341 struct buffer *b
3343 3342 = ALLOCATE_PSEUDOVECTOR (struct buffer, cursor_in_non_selected_windows_,
3343 PVEC_BUFFER);
3344 BUFFER_PVEC_INIT (b); 3344 BUFFER_PVEC_INIT (b);
3345 /* Put B on the chain of all buffers including killed ones. */
3346 b->next = all_buffers;
3347 all_buffers = b;
3348 /* Note that the rest fields of B are not initialized. */ 3345 /* Note that the rest fields of B are not initialized. */
3349 return b; 3346 return b;
3350} 3347}
@@ -4604,40 +4601,6 @@ live_vector_p (struct mem_node *m, void *p)
4604 return !NILP (live_vector_holding (m, p)); 4601 return !NILP (live_vector_holding (m, p));
4605} 4602}
4606 4603
4607/* If P is a pointer into a valid buffer object, return the buffer.
4608 Otherwise, return nil. M is a pointer to the mem_block for P.
4609 If IGNORE_KILLED is non-zero, treat killed buffers as invalid. */
4610
4611static Lisp_Object
4612live_buffer_holding (struct mem_node *m, void *p, bool ignore_killed)
4613{
4614 /* P must point into the block, and the buffer must not
4615 have been killed unless ALL-BUFFERS is true. */
4616 if (m->type == MEM_TYPE_BUFFER)
4617 {
4618 struct buffer *b = m->start;
4619 char *cb = m->start;
4620 char *cp = p;
4621 ptrdiff_t offset = cp - cb;
4622 if (0 <= offset && offset < sizeof *b
4623 && !(ignore_killed && NILP (b->name_)))
4624 {
4625 Lisp_Object obj;
4626 XSETBUFFER (obj, b);
4627 return obj;
4628 }
4629 }
4630 return Qnil;
4631}
4632
4633/* If P is a pointer into a live (valid and not killed) buffer object,
4634 return non-zero. */
4635static bool
4636live_buffer_p (struct mem_node *m, void *p)
4637{
4638 return !NILP (live_buffer_holding (m, p, true));
4639}
4640
4641/* Mark OBJ if we can prove it's a Lisp_Object. */ 4604/* Mark OBJ if we can prove it's a Lisp_Object. */
4642 4605
4643static void 4606static void
@@ -4692,8 +4655,7 @@ mark_maybe_object (Lisp_Object obj)
4692 break; 4655 break;
4693 4656
4694 case Lisp_Vectorlike: 4657 case Lisp_Vectorlike:
4695 mark_p = (EQ (obj, live_vector_holding (m, po)) 4658 mark_p = (EQ (obj, live_vector_holding (m, po)));
4696 || EQ (obj, live_buffer_holding (m, po, false)));
4697 break; 4659 break;
4698 4660
4699 default: 4661 default:
@@ -4762,10 +4724,6 @@ mark_maybe_pointer (void *p)
4762 /* Nothing to do; not a pointer to Lisp memory. */ 4724 /* Nothing to do; not a pointer to Lisp memory. */
4763 break; 4725 break;
4764 4726
4765 case MEM_TYPE_BUFFER:
4766 obj = live_buffer_holding (m, p, false);
4767 break;
4768
4769 case MEM_TYPE_CONS: 4727 case MEM_TYPE_CONS:
4770 obj = live_cons_holding (m, p); 4728 obj = live_cons_holding (m, p);
4771 break; 4729 break;
@@ -5165,9 +5123,6 @@ valid_lisp_object_p (Lisp_Object obj)
5165 case MEM_TYPE_SPARE: 5123 case MEM_TYPE_SPARE:
5166 return 0; 5124 return 0;
5167 5125
5168 case MEM_TYPE_BUFFER:
5169 return live_buffer_p (m, p) ? 1 : 2;
5170
5171 case MEM_TYPE_CONS: 5126 case MEM_TYPE_CONS:
5172 return live_cons_p (m, p); 5127 return live_cons_p (m, p);
5173 5128
@@ -5984,7 +5939,7 @@ maybe_garbage_collect (void)
5984void 5939void
5985garbage_collect (void) 5940garbage_collect (void)
5986{ 5941{
5987 struct buffer *nextb; 5942 Lisp_Object tail, buffer;
5988 char stack_top_variable; 5943 char stack_top_variable;
5989 bool message_p; 5944 bool message_p;
5990 ptrdiff_t count = SPECPDL_INDEX (); 5945 ptrdiff_t count = SPECPDL_INDEX ();
@@ -6000,8 +5955,8 @@ garbage_collect (void)
6000 5955
6001 /* Don't keep undo information around forever. 5956 /* Don't keep undo information around forever.
6002 Do this early on, so it is no problem if the user quits. */ 5957 Do this early on, so it is no problem if the user quits. */
6003 FOR_EACH_BUFFER (nextb) 5958 FOR_EACH_LIVE_BUFFER (tail, buffer)
6004 compact_buffer (nextb); 5959 compact_buffer (XBUFFER (buffer));
6005 5960
6006 byte_ct tot_before = (profiler_memory_running 5961 byte_ct tot_before = (profiler_memory_running
6007 ? total_bytes_of_live_objects () 5962 ? total_bytes_of_live_objects ()
@@ -6091,8 +6046,9 @@ garbage_collect (void)
6091 6046
6092 compact_font_caches (); 6047 compact_font_caches ();
6093 6048
6094 FOR_EACH_BUFFER (nextb) 6049 FOR_EACH_LIVE_BUFFER (tail, buffer)
6095 { 6050 {
6051 struct buffer *nextb = XBUFFER (buffer);
6096 if (!EQ (BVAR (nextb, undo_list), Qt)) 6052 if (!EQ (BVAR (nextb, undo_list), Qt))
6097 bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list))); 6053 bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list)));
6098 /* Now that we have stripped the elements that need not be 6054 /* Now that we have stripped the elements that need not be
@@ -6357,7 +6313,12 @@ mark_buffer (struct buffer *buffer)
6357 6313
6358 /* For now, we just don't mark the undo_list. It's done later in 6314 /* For now, we just don't mark the undo_list. It's done later in
6359 a special way just before the sweep phase, and after stripping 6315 a special way just before the sweep phase, and after stripping
6360 some of its elements that are not needed any more. */ 6316 some of its elements that are not needed any more.
6317 Note: this later processing is only done for live buffers, so
6318 for dead buffers, the undo_list should be nil (set by Fkill_buffer),
6319 but just to be on the safe side, we mark it here. */
6320 if (!BUFFER_LIVE_P (buffer))
6321 mark_object (BVAR (buffer, undo_list));
6361 6322
6362 mark_overlay (buffer->overlays_before); 6323 mark_overlay (buffer->overlays_before);
6363 mark_overlay (buffer->overlays_after); 6324 mark_overlay (buffer->overlays_after);
@@ -6621,23 +6582,12 @@ mark_object (Lisp_Object arg)
6621 = PSEUDOVECTOR_TYPE (ptr); 6582 = PSEUDOVECTOR_TYPE (ptr);
6622 6583
6623 if (pvectype != PVEC_SUBR && 6584 if (pvectype != PVEC_SUBR &&
6624 pvectype != PVEC_BUFFER &&
6625 !main_thread_p (po)) 6585 !main_thread_p (po))
6626 CHECK_LIVE (live_vector_p); 6586 CHECK_LIVE (live_vector_p);
6627 6587
6628 switch (pvectype) 6588 switch (pvectype)
6629 { 6589 {
6630 case PVEC_BUFFER: 6590 case PVEC_BUFFER:
6631#if GC_CHECK_MARKED_OBJECTS
6632 {
6633 struct buffer *b;
6634 FOR_EACH_BUFFER (b)
6635 if (b == po)
6636 break;
6637 if (b == NULL)
6638 emacs_abort ();
6639 }
6640#endif /* GC_CHECK_MARKED_OBJECTS */
6641 mark_buffer ((struct buffer *) ptr); 6591 mark_buffer ((struct buffer *) ptr);
6642 break; 6592 break;
6643 6593
@@ -7126,25 +7076,17 @@ NO_INLINE /* For better stack traces */
7126static void 7076static void
7127sweep_buffers (void) 7077sweep_buffers (void)
7128{ 7078{
7129 struct buffer *buffer, **bprev = &all_buffers; 7079 Lisp_Object tail, buf;
7130 7080
7131 gcstat.total_buffers = 0; 7081 gcstat.total_buffers = 0;
7132 for (buffer = all_buffers; buffer; buffer = *bprev) 7082 FOR_EACH_LIVE_BUFFER (tail, buf)
7133 if (!vectorlike_marked_p (&buffer->header)) 7083 {
7134 { 7084 struct buffer *buffer = XBUFFER (buf);
7135 *bprev = buffer->next; 7085 /* Do not use buffer_(set|get)_intervals here. */
7136 lisp_free (buffer); 7086 buffer->text->intervals = balance_intervals (buffer->text->intervals);
7137 } 7087 unchain_dead_markers (buffer);
7138 else 7088 gcstat.total_buffers++;
7139 { 7089 }
7140 if (!pdumper_object_p (buffer))
7141 XUNMARK_VECTOR (buffer);
7142 /* Do not use buffer_(set|get)_intervals here. */
7143 buffer->text->intervals = balance_intervals (buffer->text->intervals);
7144 unchain_dead_markers (buffer);
7145 gcstat.total_buffers++;
7146 bprev = &buffer->next;
7147 }
7148} 7090}
7149 7091
7150/* Sweep: find all structures not marked, and free them. */ 7092/* Sweep: find all structures not marked, and free them. */
diff --git a/src/buffer.c b/src/buffer.c
index 70598a7a22a..d8842a6d770 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -51,11 +51,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
51#include "w32heap.h" /* for mmap_* */ 51#include "w32heap.h" /* for mmap_* */
52#endif 52#endif
53 53
54/* First buffer in chain of all buffers (in reverse order of creation).
55 Threaded through ->header.next.buffer. */
56
57struct buffer *all_buffers;
58
59/* This structure holds the default values of the buffer-local variables 54/* This structure holds the default values of the buffer-local variables
60 defined with DEFVAR_PER_BUFFER, that have special slots in each buffer. 55 defined with DEFVAR_PER_BUFFER, that have special slots in each buffer.
61 The default value occupies the same slot in this structure 56 The default value occupies the same slot in this structure
@@ -1786,15 +1781,11 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1786 ask questions or their hooks get errors. */ 1781 ask questions or their hooks get errors. */
1787 if (!b->base_buffer && b->indirections > 0) 1782 if (!b->base_buffer && b->indirections > 0)
1788 { 1783 {
1789 struct buffer *other; 1784 Lisp_Object tail, other;
1790 1785
1791 FOR_EACH_BUFFER (other) 1786 FOR_EACH_LIVE_BUFFER (tail, other)
1792 if (other->base_buffer == b) 1787 if (XBUFFER (other)->base_buffer == b)
1793 { 1788 Fkill_buffer (other);
1794 Lisp_Object buf;
1795 XSETBUFFER (buf, other);
1796 Fkill_buffer (buf);
1797 }
1798 1789
1799 /* Exit if we now have killed the base buffer (Bug#11665). */ 1790 /* Exit if we now have killed the base buffer (Bug#11665). */
1800 if (!BUFFER_LIVE_P (b)) 1791 if (!BUFFER_LIVE_P (b))
@@ -1849,6 +1840,9 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1849 1840
1850 tem = Vinhibit_quit; 1841 tem = Vinhibit_quit;
1851 Vinhibit_quit = Qt; 1842 Vinhibit_quit = Qt;
1843 /* Once the buffer is removed from Vbuffer_alist, its undo_list field is
1844 not traced by the GC in the same way. So set it to nil early. */
1845 bset_undo_list (b, Qnil);
1852 /* Remove the buffer from the list of all buffers. */ 1846 /* Remove the buffer from the list of all buffers. */
1853 Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist); 1847 Vbuffer_alist = Fdelq (Frassq (buffer, Vbuffer_alist), Vbuffer_alist);
1854 /* If replace_buffer_in_windows didn't do its job fix that now. */ 1848 /* If replace_buffer_in_windows didn't do its job fix that now. */
@@ -1963,7 +1957,6 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1963 } 1957 }
1964 bset_width_table (b, Qnil); 1958 bset_width_table (b, Qnil);
1965 unblock_input (); 1959 unblock_input ();
1966 bset_undo_list (b, Qnil);
1967 1960
1968 /* Run buffer-list-update-hook. */ 1961 /* Run buffer-list-update-hook. */
1969 if (!NILP (Vrun_hooks) && !b->inhibit_buffer_hooks) 1962 if (!NILP (Vrun_hooks) && !b->inhibit_buffer_hooks)
@@ -2351,10 +2344,10 @@ results, see Info node `(elisp)Swapping Text'. */)
2351 error ("Cannot swap indirect buffers's text"); 2344 error ("Cannot swap indirect buffers's text");
2352 2345
2353 { /* This is probably harder to make work. */ 2346 { /* This is probably harder to make work. */
2354 struct buffer *other; 2347 Lisp_Object tail, other;
2355 FOR_EACH_BUFFER (other) 2348 FOR_EACH_LIVE_BUFFER (tail, other)
2356 if (other->base_buffer == other_buffer 2349 if (XBUFFER (other)->base_buffer == other_buffer
2357 || other->base_buffer == current_buffer) 2350 || XBUFFER (other)->base_buffer == current_buffer)
2358 error ("One of the buffers to swap has indirect buffers"); 2351 error ("One of the buffers to swap has indirect buffers");
2359 } 2352 }
2360 2353
@@ -2502,7 +2495,7 @@ current buffer is cleared. */)
2502 (Lisp_Object flag) 2495 (Lisp_Object flag)
2503{ 2496{
2504 struct Lisp_Marker *tail, *markers; 2497 struct Lisp_Marker *tail, *markers;
2505 struct buffer *other; 2498 Lisp_Object btail, other;
2506 ptrdiff_t begv, zv; 2499 ptrdiff_t begv, zv;
2507 bool narrowed = (BEG != BEGV || Z != ZV); 2500 bool narrowed = (BEG != BEGV || Z != ZV);
2508 bool modified_p = !NILP (Fbuffer_modified_p (Qnil)); 2501 bool modified_p = !NILP (Fbuffer_modified_p (Qnil));
@@ -2755,13 +2748,16 @@ current buffer is cleared. */)
2755 2748
2756 /* Copy this buffer's new multibyte status 2749 /* Copy this buffer's new multibyte status
2757 into all of its indirect buffers. */ 2750 into all of its indirect buffers. */
2758 FOR_EACH_BUFFER (other) 2751 FOR_EACH_LIVE_BUFFER (btail, other)
2759 if (other->base_buffer == current_buffer && BUFFER_LIVE_P (other)) 2752 {
2760 { 2753 struct buffer *o = XBUFFER (other);
2761 BVAR (other, enable_multibyte_characters) 2754 if (o->base_buffer == current_buffer && BUFFER_LIVE_P (o))
2762 = BVAR (current_buffer, enable_multibyte_characters); 2755 {
2763 other->prevent_redisplay_optimizations_p = 1; 2756 BVAR (o, enable_multibyte_characters)
2764 } 2757 = BVAR (current_buffer, enable_multibyte_characters);
2758 o->prevent_redisplay_optimizations_p = true;
2759 }
2760 }
2765 2761
2766 /* Restore the modifiedness of the buffer. */ 2762 /* Restore the modifiedness of the buffer. */
2767 if (!modified_p && !NILP (Fbuffer_modified_p (Qnil))) 2763 if (!modified_p && !NILP (Fbuffer_modified_p (Qnil)))
@@ -5327,8 +5323,6 @@ init_buffer_once (void)
5327 Vbuffer_alist = Qnil; 5323 Vbuffer_alist = Qnil;
5328 current_buffer = 0; 5324 current_buffer = 0;
5329 pdumper_remember_lv_ptr_raw (&current_buffer, Lisp_Vectorlike); 5325 pdumper_remember_lv_ptr_raw (&current_buffer, Lisp_Vectorlike);
5330 all_buffers = 0;
5331 pdumper_remember_lv_ptr_raw (&all_buffers, Lisp_Vectorlike);
5332 5326
5333 QSFundamental = build_pure_c_string ("Fundamental"); 5327 QSFundamental = build_pure_c_string ("Fundamental");
5334 5328
@@ -5359,7 +5353,7 @@ init_buffer (void)
5359#ifdef USE_MMAP_FOR_BUFFERS 5353#ifdef USE_MMAP_FOR_BUFFERS
5360 if (dumped_with_unexec_p ()) 5354 if (dumped_with_unexec_p ())
5361 { 5355 {
5362 struct buffer *b; 5356 Lisp_Object tail, buffer;
5363 5357
5364#ifndef WINDOWSNT 5358#ifndef WINDOWSNT
5365 /* These must be reset in the dumped Emacs, to avoid stale 5359 /* These must be reset in the dumped Emacs, to avoid stale
@@ -5381,23 +5375,13 @@ init_buffer (void)
5381 " *code-conversion-work*". They are created by 5375 " *code-conversion-work*". They are created by
5382 init_buffer_once and init_window_once (which are not called 5376 init_buffer_once and init_window_once (which are not called
5383 in the dumped Emacs), and by the first call to coding.c routines. */ 5377 in the dumped Emacs), and by the first call to coding.c routines. */
5384 FOR_EACH_BUFFER (b) 5378 FOR_EACH_LIVE_BUFFER (tail, buffer)
5385 { 5379 {
5380 struct buffer *b = XBUFFER (buffer);
5386 b->text->beg = NULL; 5381 b->text->beg = NULL;
5387 enlarge_buffer_text (b, 0); 5382 enlarge_buffer_text (b, 0);
5388 } 5383 }
5389 } 5384 }
5390 else
5391 {
5392 struct buffer *b;
5393
5394 /* Only buffers with allocated buffer text should be present at
5395 this point in temacs. */
5396 FOR_EACH_BUFFER (b)
5397 {
5398 eassert (b->text->beg != NULL);
5399 }
5400 }
5401#endif /* USE_MMAP_FOR_BUFFERS */ 5385#endif /* USE_MMAP_FOR_BUFFERS */
5402 5386
5403 AUTO_STRING (scratch, "*scratch*"); 5387 AUTO_STRING (scratch, "*scratch*");
diff --git a/src/buffer.h b/src/buffer.h
index 31f497ea40a..abb1294d038 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -570,9 +570,6 @@ struct buffer
570 In an indirect buffer, this is the own_text field of another buffer. */ 570 In an indirect buffer, this is the own_text field of another buffer. */
571 struct buffer_text *text; 571 struct buffer_text *text;
572 572
573 /* Next buffer, in chain of all buffers, including killed ones. */
574 struct buffer *next;
575
576 /* Char position of point in buffer. */ 573 /* Char position of point in buffer. */
577 ptrdiff_t pt; 574 ptrdiff_t pt;
578 575
@@ -1104,15 +1101,6 @@ BUFFER_CHECK_INDIRECTION (struct buffer *b)
1104 } 1101 }
1105} 1102}
1106 1103
1107/* Chain of all buffers, including killed ones. */
1108
1109extern struct buffer *all_buffers;
1110
1111/* Used to iterate over the chain above. */
1112
1113#define FOR_EACH_BUFFER(b) \
1114 for ((b) = all_buffers; (b); (b) = (b)->next)
1115
1116/* This structure holds the default values of the buffer-local variables 1104/* This structure holds the default values of the buffer-local variables
1117 that have special slots in each buffer. 1105 that have special slots in each buffer.
1118 The default value occupies the same slot in this structure 1106 The default value occupies the same slot in this structure
diff --git a/src/decompress.c b/src/decompress.c
index 5d246387e76..8e8f2443111 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -87,7 +87,7 @@ unwind_decompress (void *ddata)
87 0); 87 0);
88 update_compositions (data->start, data->start, CHECK_HEAD); 88 update_compositions (data->start, data->start, CHECK_HEAD);
89 /* "Balance" the before-change-functions call, which would 89 /* "Balance" the before-change-functions call, which would
90 otherwise be left "hanging". */ 90 otherwise be left "hanging". */
91 signal_after_change (data->orig, data->start - data->orig, 91 signal_after_change (data->orig, data->start - data->orig,
92 data->start - data->orig); 92 data->start - data->orig);
93 } 93 }
@@ -159,7 +159,7 @@ This function can be called only in unibyte buffers. */)
159 istart = XFIXNUM (start); 159 istart = XFIXNUM (start);
160 iend = XFIXNUM (end); 160 iend = XFIXNUM (end);
161 161
162 /* Do the following before manipulating the gap. */ 162 /* Do the following before manipulating the gap. */
163 modify_text (istart, iend); 163 modify_text (istart, iend);
164 164
165 move_gap_both (iend, iend); 165 move_gap_both (iend, iend);
@@ -224,7 +224,7 @@ This function can be called only in unibyte buffers. */)
224 unwind_data.start = 0; 224 unwind_data.start = 0;
225 225
226 /* Delete the compressed data. */ 226 /* Delete the compressed data. */
227 del_range_2 (istart, istart, /* byte and char offsets are the same. */ 227 del_range_2 (istart, istart, /* byte and char offsets are the same */
228 iend, iend, 0); 228 iend, iend, 0);
229 229
230 signal_after_change (istart, iend - istart, unwind_data.nbytes); 230 signal_after_change (istart, iend - istart, unwind_data.nbytes);
diff --git a/src/dispextern.h b/src/dispextern.h
index 08380f1f17f..555946f84cb 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1693,12 +1693,17 @@ struct face
1693 int fontset; 1693 int fontset;
1694 1694
1695 /* Non-zero means characters in this face have a box of that 1695 /* Non-zero means characters in this face have a box of that
1696 thickness around them. If this value is negative, its absolute 1696 thickness around them. Vertical (left and right) and horizontal
1697 value indicates the thickness, and the horizontal (top and 1697 (top and bottom) borders size can be set separatedly using an
1698 bottom) borders of box are drawn inside of the character glyphs' 1698 associated list of two ints in the form
1699 area. The vertical (left and right) borders of the box are drawn 1699 (vertical_size . horizontal_size). In case one of the value is
1700 in the same way as when this value is positive. */ 1700 negative, its absolute value indicates the thickness, and the
1701 int box_line_width; 1701 borders of box are drawn inside of the character glyphs' area
1702 potentially over the glyph itself but the glyph drawing size is
1703 not increase. If a (signed) int N is use instead of a list, it
1704 is the same as setting ( abs(N) . N ) values. */
1705 int box_vertical_line_width;
1706 int box_horizontal_line_width;
1702 1707
1703 /* Type of box drawn. A value of FACE_NO_BOX means no box is drawn 1708 /* Type of box drawn. A value of FACE_NO_BOX means no box is drawn
1704 around text in this face. A value of FACE_SIMPLE_BOX means a box 1709 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 9bec3691786..e41a698a2ff 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -1043,7 +1043,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
1043 1043
1044 r.origin.x = s->x; 1044 r.origin.x = s->x;
1045 if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) 1045 if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p)
1046 r.origin.x += abs (s->face->box_line_width); 1046 r.origin.x += max (s->face->box_vertical_line_width, 0);
1047 1047
1048 r.origin.y = s->y; 1048 r.origin.y = s->y;
1049 r.size.height = FONT_HEIGHT (font); 1049 r.size.height = FONT_HEIGHT (font);
@@ -1105,7 +1105,7 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
1105 { 1105 {
1106 NSRect br = r; 1106 NSRect br = r;
1107 int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f); 1107 int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
1108 int mbox_line_width = max (s->face->box_line_width, 0); 1108 int mbox_line_width = max (s->face->box_vertical_line_width, 0);
1109 1109
1110 if (s->row->full_width_p) 1110 if (s->row->full_width_p)
1111 { 1111 {
@@ -1129,9 +1129,10 @@ nsfont_draw (struct glyph_string *s, int from, int to, int x, int y,
1129 } 1129 }
1130 else 1130 else
1131 { 1131 {
1132 int correction = abs (s->face->box_line_width)+1; 1132 int correction = abs (s->face->box_horizontal_line_width)+1;
1133 br.origin.y += correction; 1133 br.origin.y += correction;
1134 br.size.height -= 2*correction; 1134 br.size.height -= 2*correction;
1135 correction = abs (s->face->box_vertical_line_width)+1;
1135 br.origin.x += correction; 1136 br.origin.x += correction;
1136 br.size.width -= 2*correction; 1137 br.size.width -= 2*correction;
1137 } 1138 }
diff --git a/src/nsterm.m b/src/nsterm.m
index 04fc0512234..3ce223307ba 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3639,8 +3639,8 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face,
3639} 3639}
3640 3640
3641static void 3641static void
3642ns_draw_box (NSRect r, CGFloat thickness, NSColor *col, 3642ns_draw_box (NSRect r, CGFloat hthickness, CGFloat vthickness,
3643 char left_p, char right_p) 3643 NSColor *col, char left_p, char right_p)
3644/* -------------------------------------------------------------------------- 3644/* --------------------------------------------------------------------------
3645 Draw an unfilled rect inside r, optionally leaving left and/or right open. 3645 Draw an unfilled rect inside r, optionally leaving left and/or right open.
3646 Note we can't just use an NSDrawRect command, because of the possibility 3646 Note we can't just use an NSDrawRect command, because of the possibility
@@ -3651,28 +3651,28 @@ ns_draw_box (NSRect r, CGFloat thickness, NSColor *col,
3651 [col set]; 3651 [col set];
3652 3652
3653 /* top, bottom */ 3653 /* top, bottom */
3654 s.size.height = thickness; 3654 s.size.height = hthickness;
3655 NSRectFill (s); 3655 NSRectFill (s);
3656 s.origin.y += r.size.height - thickness; 3656 s.origin.y += r.size.height - hthickness;
3657 NSRectFill (s); 3657 NSRectFill (s);
3658 3658
3659 s.size.height = r.size.height; 3659 s.size.height = r.size.height;
3660 s.origin.y = r.origin.y; 3660 s.origin.y = r.origin.y;
3661 3661
3662 /* left, right (optional) */ 3662 /* left, right (optional) */
3663 s.size.width = thickness; 3663 s.size.width = vthickness;
3664 if (left_p) 3664 if (left_p)
3665 NSRectFill (s); 3665 NSRectFill (s);
3666 if (right_p) 3666 if (right_p)
3667 { 3667 {
3668 s.origin.x += r.size.width - thickness; 3668 s.origin.x += r.size.width - vthickness;
3669 NSRectFill (s); 3669 NSRectFill (s);
3670 } 3670 }
3671} 3671}
3672 3672
3673 3673
3674static void 3674static void
3675ns_draw_relief (NSRect r, int thickness, char raised_p, 3675ns_draw_relief (NSRect r, int hthickness, int vthickness, char raised_p,
3676 char top_p, char bottom_p, char left_p, char right_p, 3676 char top_p, char bottom_p, char left_p, char right_p,
3677 struct glyph_string *s) 3677 struct glyph_string *s)
3678/* -------------------------------------------------------------------------- 3678/* --------------------------------------------------------------------------
@@ -3722,27 +3722,27 @@ ns_draw_relief (NSRect r, int thickness, char raised_p,
3722 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */ 3722 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
3723 3723
3724 /* top */ 3724 /* top */
3725 sr.size.height = thickness; 3725 sr.size.height = hthickness;
3726 if (top_p) NSRectFill (sr); 3726 if (top_p) NSRectFill (sr);
3727 3727
3728 /* left */ 3728 /* left */
3729 sr.size.height = r.size.height; 3729 sr.size.height = r.size.height;
3730 sr.size.width = thickness; 3730 sr.size.width = vthickness;
3731 if (left_p) NSRectFill (sr); 3731 if (left_p) NSRectFill (sr);
3732 3732
3733 [(raised_p ? darkCol : lightCol) set]; 3733 [(raised_p ? darkCol : lightCol) set];
3734 3734
3735 /* bottom */ 3735 /* bottom */
3736 sr.size.width = r.size.width; 3736 sr.size.width = r.size.width;
3737 sr.size.height = thickness; 3737 sr.size.height = hthickness;
3738 sr.origin.y += r.size.height - thickness; 3738 sr.origin.y += r.size.height - hthickness;
3739 if (bottom_p) NSRectFill (sr); 3739 if (bottom_p) NSRectFill (sr);
3740 3740
3741 /* right */ 3741 /* right */
3742 sr.size.height = r.size.height; 3742 sr.size.height = r.size.height;
3743 sr.origin.y = r.origin.y; 3743 sr.origin.y = r.origin.y;
3744 sr.size.width = thickness; 3744 sr.size.width = vthickness;
3745 sr.origin.x += r.size.width - thickness; 3745 sr.origin.x += r.size.width - vthickness;
3746 if (right_p) NSRectFill (sr); 3746 if (right_p) NSRectFill (sr);
3747} 3747}
3748 3748
@@ -3758,7 +3758,7 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s)
3758 char left_p, right_p; 3758 char left_p, right_p;
3759 struct glyph *last_glyph; 3759 struct glyph *last_glyph;
3760 NSRect r; 3760 NSRect r;
3761 int thickness; 3761 int hthickness, vthickness;
3762 struct face *face; 3762 struct face *face;
3763 3763
3764 if (s->hl == DRAW_MOUSE_FACE) 3764 if (s->hl == DRAW_MOUSE_FACE)
@@ -3771,7 +3771,8 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s)
3771 else 3771 else
3772 face = s->face; 3772 face = s->face;
3773 3773
3774 thickness = face->box_line_width; 3774 vthickness = face->box_vertical_line_width;
3775 hthickness = face->box_horizontal_line_width;
3775 3776
3776 NSTRACE ("ns_dumpglyphs_box_or_relief"); 3777 NSTRACE ("ns_dumpglyphs_box_or_relief");
3777 3778
@@ -3796,14 +3797,15 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s)
3796 /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */ 3797 /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
3797 if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color) 3798 if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color)
3798 { 3799 {
3799 ns_draw_box (r, abs (thickness), 3800 ns_draw_box (r, abs (hthickness), abs (vthickness),
3800 ns_lookup_indexed_color (face->box_color, s->f), 3801 ns_lookup_indexed_color (face->box_color, s->f),
3801 left_p, right_p); 3802 left_p, right_p);
3802 } 3803 }
3803 else 3804 else
3804 { 3805 {
3805 ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX, 3806 ns_draw_relief (r, abs (hthickness), abs (vthickness),
3806 1, 1, left_p, right_p, s); 3807 s->face->box == FACE_RAISED_BOX,
3808 1, 1, left_p, right_p, s);
3807 } 3809 }
3808} 3810}
3809 3811
@@ -3819,7 +3821,7 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
3819 3821
3820 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/) 3822 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
3821 { 3823 {
3822 int box_line_width = max (s->face->box_line_width, 0); 3824 int box_line_width = max (s->face->box_horizontal_line_width, 0);
3823 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width 3825 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3824 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font 3826 /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font
3825 dimensions, since the actual glyphs might be much 3827 dimensions, since the actual glyphs might be much
@@ -3870,7 +3872,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
3870 -------------------------------------------------------------------------- */ 3872 -------------------------------------------------------------------------- */
3871{ 3873{
3872 EmacsImage *img = s->img->pixmap; 3874 EmacsImage *img = s->img->pixmap;
3873 int box_line_vwidth = max (s->face->box_line_width, 0); 3875 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
3874 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice); 3876 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3875 int bg_x, bg_y, bg_height; 3877 int bg_x, bg_y, bg_height;
3876 int th; 3878 int th;
@@ -3883,7 +3885,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
3883 3885
3884 if (s->face->box != FACE_NO_BOX 3886 if (s->face->box != FACE_NO_BOX
3885 && s->first_glyph->left_box_line_p && s->slice.x == 0) 3887 && s->first_glyph->left_box_line_p && s->slice.x == 0)
3886 x += abs (s->face->box_line_width); 3888 x += max (s->face->box_vertical_line_width, 0);
3887 3889
3888 bg_x = x; 3890 bg_x = x;
3889 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth; 3891 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
@@ -4003,7 +4005,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
4003 r.origin.y = y - th; 4005 r.origin.y = y - th;
4004 r.size.width = s->slice.width + 2*th-1; 4006 r.size.width = s->slice.width + 2*th-1;
4005 r.size.height = s->slice.height + 2*th-1; 4007 r.size.height = s->slice.height + 2*th-1;
4006 ns_draw_relief (r, th, raised_p, 4008 ns_draw_relief (r, th, th, raised_p,
4007 s->slice.y == 0, 4009 s->slice.y == 0,
4008 s->slice.y + s->slice.height == s->img->height, 4010 s->slice.y + s->slice.height == s->img->height,
4009 s->slice.x == 0, 4011 s->slice.x == 0,
@@ -4017,7 +4019,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
4017 { 4019 {
4018 int thickness = abs (s->img->relief); 4020 int thickness = abs (s->img->relief);
4019 if (thickness == 0) thickness = 1; 4021 if (thickness == 0) thickness = 1;
4020 ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1); 4022 ns_draw_box (br, thickness, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1);
4021 } 4023 }
4022} 4024}
4023 4025
@@ -4100,7 +4102,7 @@ ns_draw_glyph_string_foreground (struct glyph_string *s)
4100 of S to the right of that box line. */ 4102 of S to the right of that box line. */
4101 if (s->face && s->face->box != FACE_NO_BOX 4103 if (s->face && s->face->box != FACE_NO_BOX
4102 && s->first_glyph->left_box_line_p) 4104 && s->first_glyph->left_box_line_p)
4103 x = s->x + eabs (s->face->box_line_width); 4105 x = s->x + max (s->face->box_vertical_line_width, 0);
4104 else 4106 else
4105 x = s->x; 4107 x = s->x;
4106 4108
@@ -4126,7 +4128,7 @@ ns_draw_composite_glyph_string_foreground (struct glyph_string *s)
4126 of S to the right of that box line. */ 4128 of S to the right of that box line. */
4127 if (s->face && s->face->box != FACE_NO_BOX 4129 if (s->face && s->face->box != FACE_NO_BOX
4128 && s->first_glyph->left_box_line_p) 4130 && s->first_glyph->left_box_line_p)
4129 x = s->x + eabs (s->face->box_line_width); 4131 x = s->x + max (s->face->box_vertical_line_width, 0);
4130 else 4132 else
4131 x = s->x; 4133 x = s->x;
4132 4134
@@ -4142,7 +4144,7 @@ ns_draw_composite_glyph_string_foreground (struct glyph_string *s)
4142 if (s->cmp_from == 0) 4144 if (s->cmp_from == 0)
4143 { 4145 {
4144 NSRect r = NSMakeRect (s->x, s->y, s->width-1, s->height -1); 4146 NSRect r = NSMakeRect (s->x, s->y, s->width-1, s->height -1);
4145 ns_draw_box (r, 1, FRAME_CURSOR_COLOR (s->f), 1, 1); 4147 ns_draw_box (r, 1, 1, FRAME_CURSOR_COLOR (s->f), 1, 1);
4146 } 4148 }
4147 } 4149 }
4148 else if (! s->first_glyph->u.cmp.automatic) 4150 else if (! s->first_glyph->u.cmp.automatic)
diff --git a/src/pdumper.c b/src/pdumper.c
index 55f95fd0e75..03c31681cd5 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2786,7 +2786,7 @@ dump_hash_table (struct dump_context *ctx,
2786static dump_off 2786static dump_off
2787dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) 2787dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2788{ 2788{
2789#if CHECK_STRUCTS && !defined HASH_buffer_375A10F5E5 2789#if CHECK_STRUCTS && !defined HASH_buffer_5DC36DBD42
2790# error "buffer changed. See CHECK_STRUCTS comment in config.h." 2790# error "buffer changed. See CHECK_STRUCTS comment in config.h."
2791#endif 2791#endif
2792 struct buffer munged_buffer = *in_buffer; 2792 struct buffer munged_buffer = *in_buffer;
@@ -2862,8 +2862,6 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2862 ctx->obj_offset + dump_offsetof (struct buffer, text), 2862 ctx->obj_offset + dump_offsetof (struct buffer, text),
2863 base_offset + dump_offsetof (struct buffer, own_text)); 2863 base_offset + dump_offsetof (struct buffer, own_text));
2864 2864
2865 dump_field_lv_rawptr (ctx, out, buffer, &buffer->next,
2866 Lisp_Vectorlike, WEIGHT_NORMAL);
2867 DUMP_FIELD_COPY (out, buffer, pt); 2865 DUMP_FIELD_COPY (out, buffer, pt);
2868 DUMP_FIELD_COPY (out, buffer, pt_byte); 2866 DUMP_FIELD_COPY (out, buffer, pt_byte);
2869 DUMP_FIELD_COPY (out, buffer, begv); 2867 DUMP_FIELD_COPY (out, buffer, begv);
diff --git a/src/w32term.c b/src/w32term.c
index 76cf6bd6964..5fa77d58e10 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -888,10 +888,10 @@ static void w32_draw_image_foreground_1 (struct glyph_string *, HBITMAP);
888static void w32_clear_glyph_string_rect (struct glyph_string *, int, 888static void w32_clear_glyph_string_rect (struct glyph_string *, int,
889 int, int, int); 889 int, int, int);
890static void w32_draw_relief_rect (struct frame *, int, int, int, int, 890static void w32_draw_relief_rect (struct frame *, int, int, int, int,
891 int, int, int, int, int, int, 891 int, int, int, int, int, int, int,
892 RECT *); 892 RECT *);
893static void w32_draw_box_rect (struct glyph_string *, int, int, int, int, 893static void w32_draw_box_rect (struct glyph_string *, int, int, int, int,
894 int, bool, bool, RECT *); 894 int, int, bool, bool, RECT *);
895 895
896 896
897/* Set S->gc to a suitable GC for drawing glyph string S in cursor 897/* Set S->gc to a suitable GC for drawing glyph string S in cursor
@@ -1160,7 +1160,7 @@ w32_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1160 shouldn't be drawn in the first place. */ 1160 shouldn't be drawn in the first place. */
1161 if (!s->background_filled_p) 1161 if (!s->background_filled_p)
1162 { 1162 {
1163 int box_line_width = max (s->face->box_line_width, 0); 1163 int box_line_width = max (s->face->box_horizontal_line_width, 0);
1164 1164
1165#if 0 /* TODO: stipple */ 1165#if 0 /* TODO: stipple */
1166 if (s->stippled_p) 1166 if (s->stippled_p)
@@ -1206,7 +1206,7 @@ w32_draw_glyph_string_foreground (struct glyph_string *s)
1206 of S to the right of that box line. */ 1206 of S to the right of that box line. */
1207 if (s->face->box != FACE_NO_BOX 1207 if (s->face->box != FACE_NO_BOX
1208 && s->first_glyph->left_box_line_p) 1208 && s->first_glyph->left_box_line_p)
1209 x = s->x + eabs (s->face->box_line_width); 1209 x = s->x + max (s->face->box_vertical_line_width, 0);
1210 else 1210 else
1211 x = s->x; 1211 x = s->x;
1212 1212
@@ -1264,7 +1264,7 @@ w32_draw_composite_glyph_string_foreground (struct glyph_string *s)
1264 of S to the right of that box line. */ 1264 of S to the right of that box line. */
1265 if (s->face && s->face->box != FACE_NO_BOX 1265 if (s->face && s->face->box != FACE_NO_BOX
1266 && s->first_glyph->left_box_line_p) 1266 && s->first_glyph->left_box_line_p)
1267 x = s->x + eabs (s->face->box_line_width); 1267 x = s->x + max (s->face->box_vertical_line_width, 0);
1268 else 1268 else
1269 x = s->x; 1269 x = s->x;
1270 1270
@@ -1361,7 +1361,7 @@ w32_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1361 of S to the right of that box line. */ 1361 of S to the right of that box line. */
1362 if (s->face->box != FACE_NO_BOX 1362 if (s->face->box != FACE_NO_BOX
1363 && s->first_glyph->left_box_line_p) 1363 && s->first_glyph->left_box_line_p)
1364 x = s->x + eabs (s->face->box_line_width); 1364 x = s->x + max (s->face->box_vertical_line_width, 0);
1365 else 1365 else
1366 x = s->x; 1366 x = s->x;
1367 1367
@@ -1617,7 +1617,7 @@ w32_setup_relief_colors (struct glyph_string *s)
1617static void 1617static void
1618w32_draw_relief_rect (struct frame *f, 1618w32_draw_relief_rect (struct frame *f,
1619 int left_x, int top_y, int right_x, int bottom_y, 1619 int left_x, int top_y, int right_x, int bottom_y,
1620 int width, int raised_p, 1620 int hwidth, int vwidth, int raised_p,
1621 int top_p, int bot_p, int left_p, int right_p, 1621 int top_p, int bot_p, int left_p, int right_p,
1622 RECT *clip_rect) 1622 RECT *clip_rect)
1623{ 1623{
@@ -1634,14 +1634,14 @@ w32_draw_relief_rect (struct frame *f,
1634 1634
1635 /* Top. */ 1635 /* Top. */
1636 if (top_p) 1636 if (top_p)
1637 for (i = 0; i < width; ++i) 1637 for (i = 0; i < hwidth; ++i)
1638 w32_fill_area (f, hdc, gc.foreground, 1638 w32_fill_area (f, hdc, gc.foreground,
1639 left_x + i * left_p, top_y + i, 1639 left_x + i * left_p, top_y + i,
1640 right_x - left_x - i * (left_p + right_p ) + 1, 1); 1640 right_x - left_x - i * (left_p + right_p ) + 1, 1);
1641 1641
1642 /* Left. */ 1642 /* Left. */
1643 if (left_p) 1643 if (left_p)
1644 for (i = 0; i < width; ++i) 1644 for (i = 0; i < vwidth; ++i)
1645 w32_fill_area (f, hdc, gc.foreground, 1645 w32_fill_area (f, hdc, gc.foreground,
1646 left_x + i, top_y + (i + 1) * top_p, 1, 1646 left_x + i, top_y + (i + 1) * top_p, 1,
1647 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1); 1647 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@@ -1653,14 +1653,14 @@ w32_draw_relief_rect (struct frame *f,
1653 1653
1654 /* Bottom. */ 1654 /* Bottom. */
1655 if (bot_p) 1655 if (bot_p)
1656 for (i = 0; i < width; ++i) 1656 for (i = 0; i < hwidth; ++i)
1657 w32_fill_area (f, hdc, gc.foreground, 1657 w32_fill_area (f, hdc, gc.foreground,
1658 left_x + i * left_p, bottom_y - i, 1658 left_x + i * left_p, bottom_y - i,
1659 right_x - left_x - i * (left_p + right_p) + 1, 1); 1659 right_x - left_x - i * (left_p + right_p) + 1, 1);
1660 1660
1661 /* Right. */ 1661 /* Right. */
1662 if (right_p) 1662 if (right_p)
1663 for (i = 0; i < width; ++i) 1663 for (i = 0; i < vwidth; ++i)
1664 w32_fill_area (f, hdc, gc.foreground, 1664 w32_fill_area (f, hdc, gc.foreground,
1665 right_x - i, top_y + (i + 1) * top_p, 1, 1665 right_x - i, top_y + (i + 1) * top_p, 1,
1666 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1); 1666 bottom_y - top_y - (i + 1) * (bot_p + top_p) + 1);
@@ -1680,31 +1680,31 @@ w32_draw_relief_rect (struct frame *f,
1680 1680
1681static void 1681static void
1682w32_draw_box_rect (struct glyph_string *s, 1682w32_draw_box_rect (struct glyph_string *s,
1683 int left_x, int top_y, int right_x, int bottom_y, int width, 1683 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
1684 bool left_p, bool right_p, RECT *clip_rect) 1684 int vwidth, bool left_p, bool right_p, RECT *clip_rect)
1685{ 1685{
1686 w32_set_clip_rectangle (s->hdc, clip_rect); 1686 w32_set_clip_rectangle (s->hdc, clip_rect);
1687 1687
1688 /* Top. */ 1688 /* Top. */
1689 w32_fill_area (s->f, s->hdc, s->face->box_color, 1689 w32_fill_area (s->f, s->hdc, s->face->box_color,
1690 left_x, top_y, right_x - left_x + 1, width); 1690 left_x, top_y, right_x - left_x + 1, hwidth);
1691 1691
1692 /* Left. */ 1692 /* Left. */
1693 if (left_p) 1693 if (left_p)
1694 { 1694 {
1695 w32_fill_area (s->f, s->hdc, s->face->box_color, 1695 w32_fill_area (s->f, s->hdc, s->face->box_color,
1696 left_x, top_y, width, bottom_y - top_y + 1); 1696 left_x, top_y, vwidth, bottom_y - top_y + 1);
1697 } 1697 }
1698 1698
1699 /* Bottom. */ 1699 /* Bottom. */
1700 w32_fill_area (s->f, s->hdc, s->face->box_color, 1700 w32_fill_area (s->f, s->hdc, s->face->box_color,
1701 left_x, bottom_y - width + 1, right_x - left_x + 1, width); 1701 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
1702 1702
1703 /* Right. */ 1703 /* Right. */
1704 if (right_p) 1704 if (right_p)
1705 { 1705 {
1706 w32_fill_area (s->f, s->hdc, s->face->box_color, 1706 w32_fill_area (s->f, s->hdc, s->face->box_color,
1707 right_x - width + 1, top_y, width, bottom_y - top_y + 1); 1707 right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
1708 } 1708 }
1709 1709
1710 w32_set_clip_rectangle (s->hdc, NULL); 1710 w32_set_clip_rectangle (s->hdc, NULL);
@@ -1716,7 +1716,7 @@ w32_draw_box_rect (struct glyph_string *s,
1716static void 1716static void
1717w32_draw_glyph_string_box (struct glyph_string *s) 1717w32_draw_glyph_string_box (struct glyph_string *s)
1718{ 1718{
1719 int width, left_x, right_x, top_y, bottom_y, last_x; 1719 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
1720 bool left_p, right_p, raised_p; 1720 bool left_p, right_p, raised_p;
1721 struct glyph *last_glyph; 1721 struct glyph *last_glyph;
1722 RECT clip_rect; 1722 RECT clip_rect;
@@ -1730,7 +1730,8 @@ w32_draw_glyph_string_box (struct glyph_string *s)
1730 ? s->first_glyph 1730 ? s->first_glyph
1731 : s->first_glyph + s->nchars - 1); 1731 : s->first_glyph + s->nchars - 1);
1732 1732
1733 width = eabs (s->face->box_line_width); 1733 vwidth = eabs (s->face->box_vertical_line_width);
1734 hwidth = eabs (s->face->box_horizontal_line_width);
1734 raised_p = s->face->box == FACE_RAISED_BOX; 1735 raised_p = s->face->box == FACE_RAISED_BOX;
1735 left_x = s->x; 1736 left_x = s->x;
1736 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p 1737 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
@@ -1751,13 +1752,13 @@ w32_draw_glyph_string_box (struct glyph_string *s)
1751 get_glyph_string_clip_rect (s, &clip_rect); 1752 get_glyph_string_clip_rect (s, &clip_rect);
1752 1753
1753 if (s->face->box == FACE_SIMPLE_BOX) 1754 if (s->face->box == FACE_SIMPLE_BOX)
1754 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, 1755 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
1755 left_p, right_p, &clip_rect); 1756 vwidth, left_p, right_p, &clip_rect);
1756 else 1757 else
1757 { 1758 {
1758 w32_setup_relief_colors (s); 1759 w32_setup_relief_colors (s);
1759 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, 1760 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
1760 width, raised_p, 1, 1, left_p, right_p, &clip_rect); 1761 vwidth, raised_p, 1, 1, left_p, right_p, &clip_rect);
1761 } 1762 }
1762} 1763}
1763 1764
@@ -1795,7 +1796,7 @@ w32_draw_image_foreground (struct glyph_string *s)
1795 if (s->face->box != FACE_NO_BOX 1796 if (s->face->box != FACE_NO_BOX
1796 && s->first_glyph->left_box_line_p 1797 && s->first_glyph->left_box_line_p
1797 && s->slice.x == 0) 1798 && s->slice.x == 0)
1798 x += eabs (s->face->box_line_width); 1799 x += max (s->face->box_vertical_line_width, 0);
1799 1800
1800 /* If there is a margin around the image, adjust x- and y-position 1801 /* If there is a margin around the image, adjust x- and y-position
1801 by that margin. */ 1802 by that margin. */
@@ -1982,7 +1983,7 @@ w32_draw_image_relief (struct glyph_string *s)
1982 if (s->face->box != FACE_NO_BOX 1983 if (s->face->box != FACE_NO_BOX
1983 && s->first_glyph->left_box_line_p 1984 && s->first_glyph->left_box_line_p
1984 && s->slice.x == 0) 1985 && s->slice.x == 0)
1985 x += eabs (s->face->box_line_width); 1986 x += max (s->face->box_vertical_line_width, 0);
1986 1987
1987 /* If there is a margin around the image, adjust x- and y-position 1988 /* If there is a margin around the image, adjust x- and y-position
1988 by that margin. */ 1989 by that margin. */
@@ -2034,7 +2035,7 @@ w32_draw_image_relief (struct glyph_string *s)
2034 2035
2035 w32_setup_relief_colors (s); 2036 w32_setup_relief_colors (s);
2036 get_glyph_string_clip_rect (s, &r); 2037 get_glyph_string_clip_rect (s, &r);
2037 w32_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p, 2038 w32_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
2038 top_p, bot_p, left_p, right_p, &r); 2039 top_p, bot_p, left_p, right_p, &r);
2039} 2040}
2040 2041
@@ -2054,7 +2055,7 @@ w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
2054 if (s->face->box != FACE_NO_BOX 2055 if (s->face->box != FACE_NO_BOX
2055 && s->first_glyph->left_box_line_p 2056 && s->first_glyph->left_box_line_p
2056 && s->slice.x == 0) 2057 && s->slice.x == 0)
2057 x += eabs (s->face->box_line_width); 2058 x += max (s->face->box_vertical_line_width, 0);
2058 2059
2059 /* If there is a margin around the image, adjust x- and y-position 2060 /* If there is a margin around the image, adjust x- and y-position
2060 by that margin. */ 2061 by that margin. */
@@ -2167,8 +2168,8 @@ static void
2167w32_draw_image_glyph_string (struct glyph_string *s) 2168w32_draw_image_glyph_string (struct glyph_string *s)
2168{ 2169{
2169 int x, y; 2170 int x, y;
2170 int box_line_hwidth = eabs (s->face->box_line_width); 2171 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
2171 int box_line_vwidth = max (s->face->box_line_width, 0); 2172 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
2172 int height, width; 2173 int height, width;
2173 HBITMAP pixmap = 0; 2174 HBITMAP pixmap = 0;
2174 2175
diff --git a/src/xdisp.c b/src/xdisp.c
index 61c798c59e8..cbdef7ad118 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2061,8 +2061,8 @@ estimate_mode_line_height (struct frame *f, enum face_id face_id)
2061 { 2061 {
2062 if (face->font) 2062 if (face->font)
2063 height = normal_char_height (face->font, -1); 2063 height = normal_char_height (face->font, -1);
2064 if (face->box_line_width > 0) 2064 if (face->box_horizontal_line_width > 0)
2065 height += 2 * face->box_line_width; 2065 height += 2 * face->box_horizontal_line_width;
2066 } 2066 }
2067 } 2067 }
2068 2068
@@ -28900,18 +28900,21 @@ produce_image_glyph (struct it *it)
28900 28900
28901 if (face->box != FACE_NO_BOX) 28901 if (face->box != FACE_NO_BOX)
28902 { 28902 {
28903 if (face->box_line_width > 0) 28903 if (face->box_horizontal_line_width > 0)
28904 { 28904 {
28905 if (slice.y == 0) 28905 if (slice.y == 0)
28906 it->ascent += face->box_line_width; 28906 it->ascent += face->box_horizontal_line_width;
28907 if (slice.y + slice.height == img->height) 28907 if (slice.y + slice.height == img->height)
28908 it->descent += face->box_line_width; 28908 it->descent += face->box_horizontal_line_width;
28909 } 28909 }
28910 28910
28911 if (it->start_of_box_run_p && slice.x == 0) 28911 if (face->box_vertical_line_width > 0)
28912 it->pixel_width += eabs (face->box_line_width); 28912 {
28913 if (it->end_of_box_run_p && slice.x + slice.width == img->width) 28913 if (it->start_of_box_run_p && slice.x == 0)
28914 it->pixel_width += eabs (face->box_line_width); 28914 it->pixel_width += face->box_vertical_line_width;
28915 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
28916 it->pixel_width += face->box_vertical_line_width;
28917 }
28915 } 28918 }
28916 28919
28917 take_vertical_position_into_account (it); 28920 take_vertical_position_into_account (it);
@@ -29009,15 +29012,18 @@ produce_xwidget_glyph (struct it *it)
29009 29012
29010 if (face->box != FACE_NO_BOX) 29013 if (face->box != FACE_NO_BOX)
29011 { 29014 {
29012 if (face->box_line_width > 0) 29015 if (face->box_horizontal_line_width > 0)
29013 { 29016 {
29014 it->ascent += face->box_line_width; 29017 it->ascent += face->box_horizontal_line_width;
29015 it->descent += face->box_line_width; 29018 it->descent += face->box_horizontal_line_width;
29016 } 29019 }
29017 29020
29018 if (it->start_of_box_run_p) 29021 if (face->box_vertical_line_width > 0)
29019 it->pixel_width += eabs (face->box_line_width); 29022 {
29020 it->pixel_width += eabs (face->box_line_width); 29023 if (it->start_of_box_run_p)
29024 it->pixel_width += face->box_vertical_line_width;
29025 it->pixel_width += face->box_vertical_line_width;
29026 }
29021 } 29027 }
29022 29028
29023 take_vertical_position_into_account (it); 29029 take_vertical_position_into_account (it);
@@ -29780,6 +29786,31 @@ produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
29780} 29786}
29781 29787
29782 29788
29789/* If face has a box, add the box thickness to the character
29790 height. If character has a box line to the left and/or
29791 right, add the box line width to the character's width. */
29792#define IT_APPLY_FACE_BOX(it, face) \
29793 do { \
29794 if (face->box != FACE_NO_BOX) \
29795 { \
29796 int thick = face->box_horizontal_line_width; \
29797 if (thick > 0) \
29798 { \
29799 it->ascent += thick; \
29800 it->descent += thick; \
29801 } \
29802 \
29803 thick = face->box_vertical_line_width; \
29804 if (thick > 0) \
29805 { \
29806 if (it->start_of_box_run_p) \
29807 it->pixel_width += thick; \
29808 if (it->end_of_box_run_p) \
29809 it->pixel_width += thick; \
29810 } \
29811 } \
29812 } while (false)
29813
29783/* RIF: 29814/* RIF:
29784 Produce glyphs/get display metrics for the display element IT is 29815 Produce glyphs/get display metrics for the display element IT is
29785 loaded with. See the description of struct it in dispextern.h 29816 loaded with. See the description of struct it in dispextern.h
@@ -29895,26 +29926,7 @@ gui_produce_glyphs (struct it *it)
29895 if (stretched_p) 29926 if (stretched_p)
29896 it->pixel_width *= XFLOATINT (it->space_width); 29927 it->pixel_width *= XFLOATINT (it->space_width);
29897 29928
29898 /* If face has a box, add the box thickness to the character 29929 IT_APPLY_FACE_BOX(it, face);
29899 height. If character has a box line to the left and/or
29900 right, add the box line width to the character's width. */
29901 if (face->box != FACE_NO_BOX)
29902 {
29903 int thick = face->box_line_width;
29904
29905 if (thick > 0)
29906 {
29907 it->ascent += thick;
29908 it->descent += thick;
29909 }
29910 else
29911 thick = -thick;
29912
29913 if (it->start_of_box_run_p)
29914 it->pixel_width += thick;
29915 if (it->end_of_box_run_p)
29916 it->pixel_width += thick;
29917 }
29918 29930
29919 /* If face has an overline, add the height of the overline 29931 /* If face has an overline, add the height of the overline
29920 (1 pixel) and a 1 pixel margin to the character height. */ 29932 (1 pixel) and a 1 pixel margin to the character height. */
@@ -30029,10 +30041,10 @@ gui_produce_glyphs (struct it *it)
30029 30041
30030 if ((it->max_ascent > 0 || it->max_descent > 0) 30042 if ((it->max_ascent > 0 || it->max_descent > 0)
30031 && face->box != FACE_NO_BOX 30043 && face->box != FACE_NO_BOX
30032 && face->box_line_width > 0) 30044 && face->box_horizontal_line_width > 0)
30033 { 30045 {
30034 it->ascent += face->box_line_width; 30046 it->ascent += face->box_horizontal_line_width;
30035 it->descent += face->box_line_width; 30047 it->descent += face->box_horizontal_line_width;
30036 } 30048 }
30037 if (!NILP (height) 30049 if (!NILP (height)
30038 && XFIXNUM (height) > it->ascent + it->descent) 30050 && XFIXNUM (height) > it->ascent + it->descent)
@@ -30439,23 +30451,7 @@ gui_produce_glyphs (struct it *it)
30439 it->pixel_width = cmp->pixel_width; 30451 it->pixel_width = cmp->pixel_width;
30440 it->ascent = it->phys_ascent = cmp->ascent; 30452 it->ascent = it->phys_ascent = cmp->ascent;
30441 it->descent = it->phys_descent = cmp->descent; 30453 it->descent = it->phys_descent = cmp->descent;
30442 if (face->box != FACE_NO_BOX) 30454 IT_APPLY_FACE_BOX(it, face);
30443 {
30444 int thick = face->box_line_width;
30445
30446 if (thick > 0)
30447 {
30448 it->ascent += thick;
30449 it->descent += thick;
30450 }
30451 else
30452 thick = - thick;
30453
30454 if (it->start_of_box_run_p)
30455 it->pixel_width += thick;
30456 if (it->end_of_box_run_p)
30457 it->pixel_width += thick;
30458 }
30459 30455
30460 /* If face has an overline, add the height of the overline 30456 /* If face has an overline, add the height of the overline
30461 (1 pixel) and a 1 pixel margin to the character height. */ 30457 (1 pixel) and a 1 pixel margin to the character height. */
@@ -30489,23 +30485,8 @@ gui_produce_glyphs (struct it *it)
30489 it->glyph_row->contains_overlapping_glyphs_p = true; 30485 it->glyph_row->contains_overlapping_glyphs_p = true;
30490 it->ascent = it->phys_ascent = metrics.ascent; 30486 it->ascent = it->phys_ascent = metrics.ascent;
30491 it->descent = it->phys_descent = metrics.descent; 30487 it->descent = it->phys_descent = metrics.descent;
30492 if (face->box != FACE_NO_BOX) 30488 IT_APPLY_FACE_BOX(it, face);
30493 {
30494 int thick = face->box_line_width;
30495 30489
30496 if (thick > 0)
30497 {
30498 it->ascent += thick;
30499 it->descent += thick;
30500 }
30501 else
30502 thick = - thick;
30503
30504 if (it->start_of_box_run_p)
30505 it->pixel_width += thick;
30506 if (it->end_of_box_run_p)
30507 it->pixel_width += thick;
30508 }
30509 /* If face has an overline, add the height of the overline 30490 /* If face has an overline, add the height of the overline
30510 (1 pixel) and a 1 pixel margin to the character height. */ 30491 (1 pixel) and a 1 pixel margin to the character height. */
30511 if (face->overline_p) 30492 if (face->overline_p)
diff --git a/src/xfaces.c b/src/xfaces.c
index 91a7a8533e8..bab142ade0f 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -3128,6 +3128,8 @@ FRAME 0 means change the face on all frames, and change the default
3128 valid_p = XFIXNUM (value) != 0; 3128 valid_p = XFIXNUM (value) != 0;
3129 else if (STRINGP (value)) 3129 else if (STRINGP (value))
3130 valid_p = SCHARS (value) > 0; 3130 valid_p = SCHARS (value) > 0;
3131 else if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value)))
3132 valid_p = true;
3131 else if (CONSP (value)) 3133 else if (CONSP (value))
3132 { 3134 {
3133 Lisp_Object tem; 3135 Lisp_Object tem;
@@ -3146,7 +3148,9 @@ FRAME 0 means change the face on all frames, and change the default
3146 3148
3147 if (EQ (k, QCline_width)) 3149 if (EQ (k, QCline_width))
3148 { 3150 {
3149 if (!FIXNUMP (v) || XFIXNUM (v) == 0) 3151 if ((!CONSP(v) || !FIXNUMP (XCAR (v)) || XFIXNUM (XCAR (v)) == 0
3152 || !FIXNUMP (XCDR (v)) || XFIXNUM (XCDR (v)) == 0)
3153 && (!FIXNUMP (v) || XFIXNUM (v) == 0))
3150 break; 3154 break;
3151 } 3155 }
3152 else if (EQ (k, QCcolor)) 3156 else if (EQ (k, QCcolor))
@@ -5815,7 +5819,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
5815 face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX], 5819 face->box_color = load_color (f, face, attrs[LFACE_BOX_INDEX],
5816 LFACE_BOX_INDEX); 5820 LFACE_BOX_INDEX);
5817 face->box = FACE_SIMPLE_BOX; 5821 face->box = FACE_SIMPLE_BOX;
5818 face->box_line_width = 1; 5822 face->box_vertical_line_width = face->box_horizontal_line_width = 1;
5819 } 5823 }
5820 else if (FIXNUMP (box)) 5824 else if (FIXNUMP (box))
5821 { 5825 {
@@ -5823,9 +5827,19 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
5823 face. */ 5827 face. */
5824 eassert (XFIXNUM (box) != 0); 5828 eassert (XFIXNUM (box) != 0);
5825 face->box = FACE_SIMPLE_BOX; 5829 face->box = FACE_SIMPLE_BOX;
5826 face->box_line_width = XFIXNUM (box); 5830 face->box_vertical_line_width = eabs(XFIXNUM (box));
5831 face->box_horizontal_line_width = XFIXNUM (box);
5832 face->box_color = face->foreground;
5833 face->box_color_defaulted_p = true;
5834 }
5835 else if (CONSP (box) && FIXNUMP (XCAR (box)) && FIXNUMP (XCDR (box)))
5836 {
5837 /* `(VWIDTH . HWIDTH)'. */
5838 face->box = FACE_SIMPLE_BOX;
5827 face->box_color = face->foreground; 5839 face->box_color = face->foreground;
5828 face->box_color_defaulted_p = true; 5840 face->box_color_defaulted_p = true;
5841 face->box_vertical_line_width = XFIXNUM (XCAR (box));
5842 face->box_horizontal_line_width = XFIXNUM (XCDR (box));
5829 } 5843 }
5830 else if (CONSP (box)) 5844 else if (CONSP (box))
5831 { 5845 {
@@ -5834,7 +5848,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
5834 face->box = FACE_SIMPLE_BOX; 5848 face->box = FACE_SIMPLE_BOX;
5835 face->box_color = face->foreground; 5849 face->box_color = face->foreground;
5836 face->box_color_defaulted_p = true; 5850 face->box_color_defaulted_p = true;
5837 face->box_line_width = 1; 5851 face->box_vertical_line_width = face->box_horizontal_line_width = 1;
5838 5852
5839 while (CONSP (box)) 5853 while (CONSP (box))
5840 { 5854 {
@@ -5850,8 +5864,14 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
5850 5864
5851 if (EQ (keyword, QCline_width)) 5865 if (EQ (keyword, QCline_width))
5852 { 5866 {
5853 if (FIXNUMP (value) && XFIXNUM (value) != 0) 5867 if (CONSP (value) && FIXNUMP (XCAR (value)) && FIXNUMP (XCDR (value))) {
5854 face->box_line_width = XFIXNUM (value); 5868 face->box_vertical_line_width = XFIXNUM (XCAR (value));
5869 face->box_horizontal_line_width = XFIXNUM (XCDR (value));
5870 }
5871 else if (FIXNUMP (value) && XFIXNUM (value) != 0) {
5872 face->box_vertical_line_width = eabs (XFIXNUM (value));
5873 face->box_horizontal_line_width = XFIXNUM (value);
5874 }
5855 } 5875 }
5856 else if (EQ (keyword, QCcolor)) 5876 else if (EQ (keyword, QCcolor))
5857 { 5877 {
@@ -6953,10 +6973,13 @@ could define a face `my-mode-default', and then in the mode setup
6953function, do: 6973function, do:
6954 6974
6955 (set (make-local-variable \\='face-remapping-alist) 6975 (set (make-local-variable \\='face-remapping-alist)
6956 \\='((default my-mode-default)))). 6976 (copy-tree \\='((default my-mode-default)))).
6957 6977
6958You probably want to use the face-remap package included in Emacs 6978You probably want to use the face-remap package included in Emacs
6959instead of manipulating face-remapping-alist directly. 6979instead of manipulating face-remapping-alist directly. Note that many
6980of the functions in that package modify the list destructively, so make
6981sure you set it to a fresh value (for instance, use `copy-tree' as in
6982the example above) before modifying.
6960 6983
6961Because Emacs normally only redraws screen areas when the underlying 6984Because Emacs normally only redraws screen areas when the underlying
6962buffer contents change, you may need to call `redraw-display' after 6985buffer contents change, you may need to call `redraw-display' after
diff --git a/src/xterm.c b/src/xterm.c
index d7d992c91b2..fc68c77048f 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)
1754 shouldn't be drawn in the first place. */ 1754 shouldn't be drawn in the first place. */
1755 if (!s->background_filled_p) 1755 if (!s->background_filled_p)
1756 { 1756 {
1757 int box_line_width = max (s->face->box_line_width, 0); 1757 int box_line_width = max (s->face->box_horizontal_line_width, 0);
1758 1758
1759 if (s->stippled_p) 1759 if (s->stippled_p)
1760 { 1760 {
@@ -1799,7 +1799,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
1799 of S to the right of that box line. */ 1799 of S to the right of that box line. */
1800 if (s->face->box != FACE_NO_BOX 1800 if (s->face->box != FACE_NO_BOX
1801 && s->first_glyph->left_box_line_p) 1801 && s->first_glyph->left_box_line_p)
1802 x = s->x + eabs (s->face->box_line_width); 1802 x = s->x + max (s->face->box_vertical_line_width, 0);
1803 else 1803 else
1804 x = s->x; 1804 x = s->x;
1805 1805
@@ -1849,7 +1849,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
1849 if (!(s->for_overlaps 1849 if (!(s->for_overlaps
1850 || (s->background_filled_p && s->hl != DRAW_CURSOR))) 1850 || (s->background_filled_p && s->hl != DRAW_CURSOR)))
1851 { 1851 {
1852 int box_line_width = max (s->face->box_line_width, 0); 1852 int box_line_width = max (s->face->box_horizontal_line_width, 0);
1853 1853
1854 if (s->stippled_p) 1854 if (s->stippled_p)
1855 { 1855 {
@@ -1893,7 +1893,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1893 of S to the right of that box line. */ 1893 of S to the right of that box line. */
1894 if (s->face && s->face->box != FACE_NO_BOX 1894 if (s->face && s->face->box != FACE_NO_BOX
1895 && s->first_glyph->left_box_line_p) 1895 && s->first_glyph->left_box_line_p)
1896 x = s->x + eabs (s->face->box_line_width); 1896 x = s->x + max (s->face->box_vertical_line_width, 0);
1897 else 1897 else
1898 x = s->x; 1898 x = s->x;
1899 1899
@@ -2004,7 +2004,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
2004 of S to the right of that box line. */ 2004 of S to the right of that box line. */
2005 if (s->face && s->face->box != FACE_NO_BOX 2005 if (s->face && s->face->box != FACE_NO_BOX
2006 && s->first_glyph->left_box_line_p) 2006 && s->first_glyph->left_box_line_p)
2007 x = s->x + eabs (s->face->box_line_width); 2007 x = s->x + max (s->face->box_vertical_line_width, 0);
2008 else 2008 else
2009 x = s->x; 2009 x = s->x;
2010 2010
@@ -2769,7 +2769,7 @@ x_setup_relief_colors (struct glyph_string *s)
2769static void 2769static void
2770x_draw_relief_rect (struct frame *f, 2770x_draw_relief_rect (struct frame *f,
2771 int left_x, int top_y, int right_x, int bottom_y, 2771 int left_x, int top_y, int right_x, int bottom_y,
2772 int width, bool raised_p, bool top_p, bool bot_p, 2772 int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p,
2773 bool left_p, bool right_p, 2773 bool left_p, bool right_p,
2774 XRectangle *clip_rect) 2774 XRectangle *clip_rect)
2775{ 2775{
@@ -2794,7 +2794,7 @@ x_draw_relief_rect (struct frame *f,
2794 if (left_p) 2794 if (left_p)
2795 { 2795 {
2796 x_fill_rectangle (f, top_left_gc, left_x, top_y, 2796 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2797 width, bottom_y + 1 - top_y); 2797 vwidth, bottom_y + 1 - top_y);
2798 if (top_p) 2798 if (top_p)
2799 corners |= 1 << CORNER_TOP_LEFT; 2799 corners |= 1 << CORNER_TOP_LEFT;
2800 if (bot_p) 2800 if (bot_p)
@@ -2802,8 +2802,8 @@ x_draw_relief_rect (struct frame *f,
2802 } 2802 }
2803 if (right_p) 2803 if (right_p)
2804 { 2804 {
2805 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y, 2805 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - vwidth, top_y,
2806 width, bottom_y + 1 - top_y); 2806 vwidth, bottom_y + 1 - top_y);
2807 if (top_p) 2807 if (top_p)
2808 corners |= 1 << CORNER_TOP_RIGHT; 2808 corners |= 1 << CORNER_TOP_RIGHT;
2809 if (bot_p) 2809 if (bot_p)
@@ -2813,25 +2813,25 @@ x_draw_relief_rect (struct frame *f,
2813 { 2813 {
2814 if (!right_p) 2814 if (!right_p)
2815 x_fill_rectangle (f, top_left_gc, left_x, top_y, 2815 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2816 right_x + 1 - left_x, width); 2816 right_x + 1 - left_x, hwidth);
2817 else 2817 else
2818 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y, 2818 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
2819 right_x + 1 - left_x, width, 1); 2819 right_x + 1 - left_x, hwidth, 1);
2820 } 2820 }
2821 if (bot_p) 2821 if (bot_p)
2822 { 2822 {
2823 if (!left_p) 2823 if (!left_p)
2824 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width, 2824 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - hwidth,
2825 right_x + 1 - left_x, width); 2825 right_x + 1 - left_x, hwidth);
2826 else 2826 else
2827 x_fill_trapezoid_for_relief (f, bottom_right_gc, 2827 x_fill_trapezoid_for_relief (f, bottom_right_gc,
2828 left_x, bottom_y + 1 - width, 2828 left_x, bottom_y + 1 - hwidth,
2829 right_x + 1 - left_x, width, 0); 2829 right_x + 1 - left_x, hwidth, 0);
2830 } 2830 }
2831 if (left_p && width != 1) 2831 if (left_p && vwidth > 1)
2832 x_fill_rectangle (f, bottom_right_gc, left_x, top_y, 2832 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2833 1, bottom_y + 1 - top_y); 2833 1, bottom_y + 1 - top_y);
2834 if (top_p && width != 1) 2834 if (top_p && hwidth > 1)
2835 x_fill_rectangle (f, bottom_right_gc, left_x, top_y, 2835 x_fill_rectangle (f, bottom_right_gc, left_x, top_y,
2836 right_x + 1 - left_x, 1); 2836 right_x + 1 - left_x, 1);
2837 if (corners) 2837 if (corners)
@@ -2865,12 +2865,12 @@ x_draw_relief_rect (struct frame *f,
2865 /* Top. */ 2865 /* Top. */
2866 if (top_p) 2866 if (top_p)
2867 { 2867 {
2868 if (width == 1) 2868 if (hwidth == 1)
2869 XDrawLine (dpy, drawable, gc, 2869 XDrawLine (dpy, drawable, gc,
2870 left_x + left_p, top_y, 2870 left_x + left_p, top_y,
2871 right_x + !right_p, top_y); 2871 right_x + !right_p, top_y);
2872 2872
2873 for (i = 1; i < width; ++i) 2873 for (i = 1; i < hwidth; ++i)
2874 XDrawLine (dpy, drawable, gc, 2874 XDrawLine (dpy, drawable, gc,
2875 left_x + i * left_p, top_y + i, 2875 left_x + i * left_p, top_y + i,
2876 right_x + 1 - i * right_p, top_y + i); 2876 right_x + 1 - i * right_p, top_y + i);
@@ -2879,13 +2879,10 @@ x_draw_relief_rect (struct frame *f,
2879 /* Left. */ 2879 /* Left. */
2880 if (left_p) 2880 if (left_p)
2881 { 2881 {
2882 if (width == 1) 2882 if (vwidth == 1)
2883 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); 2883 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2884 2884
2885 x_clear_area(f, left_x, top_y, 1, 1); 2885 for (i = 1; i < vwidth; ++i)
2886 x_clear_area(f, left_x, bottom_y, 1, 1);
2887
2888 for (i = (width > 1 ? 1 : 0); i < width; ++i)
2889 XDrawLine (dpy, drawable, gc, 2886 XDrawLine (dpy, drawable, gc,
2890 left_x + i, top_y + (i + 1) * top_p, 2887 left_x + i, top_y + (i + 1) * top_p,
2891 left_x + i, bottom_y + 1 - (i + 1) * bot_p); 2888 left_x + i, bottom_y + 1 - (i + 1) * bot_p);
@@ -2898,26 +2895,25 @@ x_draw_relief_rect (struct frame *f,
2898 gc = f->output_data.x->white_relief.gc; 2895 gc = f->output_data.x->white_relief.gc;
2899 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted); 2896 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2900 2897
2901 if (width > 1) 2898 /* Outermost top line. */
2902 { 2899 if (top_p && hwidth > 1)
2903 /* Outermost top line. */ 2900 XDrawLine (dpy, drawable, gc,
2904 if (top_p) 2901 left_x + left_p, top_y,
2905 XDrawLine (dpy, drawable, gc, 2902 right_x + !right_p, top_y);
2906 left_x + left_p, top_y,
2907 right_x + !right_p, top_y);
2908 2903
2909 /* Outermost left line. */ 2904 /* Outermost left line. */
2910 if (left_p) 2905 if (left_p && vwidth > 1)
2911 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y); 2906 XDrawLine (dpy, drawable, gc, left_x, top_y + 1, left_x, bottom_y);
2912 }
2913 2907
2914 /* Bottom. */ 2908 /* Bottom. */
2915 if (bot_p) 2909 if (bot_p)
2916 { 2910 {
2917 XDrawLine (dpy, drawable, gc, 2911 if (hwidth >= 1)
2918 left_x + left_p, bottom_y, 2912 XDrawLine (dpy, drawable, gc,
2919 right_x + !right_p, bottom_y); 2913 left_x + left_p, bottom_y,
2920 for (i = 1; i < width; ++i) 2914 right_x + !right_p, bottom_y);
2915
2916 for (i = 1; i < hwidth; ++i)
2921 XDrawLine (dpy, drawable, gc, 2917 XDrawLine (dpy, drawable, gc,
2922 left_x + i * left_p, bottom_y - i, 2918 left_x + i * left_p, bottom_y - i,
2923 right_x + 1 - i * right_p, bottom_y - i); 2919 right_x + 1 - i * right_p, bottom_y - i);
@@ -2926,9 +2922,7 @@ x_draw_relief_rect (struct frame *f,
2926 /* Right. */ 2922 /* Right. */
2927 if (right_p) 2923 if (right_p)
2928 { 2924 {
2929 x_clear_area(f, right_x, top_y, 1, 1); 2925 for (i = 0; i < vwidth; ++i)
2930 x_clear_area(f, right_x, bottom_y, 1, 1);
2931 for (i = 0; i < width; ++i)
2932 XDrawLine (dpy, drawable, gc, 2926 XDrawLine (dpy, drawable, gc,
2933 right_x - i, top_y + (i + 1) * top_p, 2927 right_x - i, top_y + (i + 1) * top_p,
2934 right_x - i, bottom_y + 1 - (i + 1) * bot_p); 2928 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
@@ -2949,8 +2943,8 @@ x_draw_relief_rect (struct frame *f,
2949 2943
2950static void 2944static void
2951x_draw_box_rect (struct glyph_string *s, 2945x_draw_box_rect (struct glyph_string *s,
2952 int left_x, int top_y, int right_x, int bottom_y, int width, 2946 int left_x, int top_y, int right_x, int bottom_y, int hwidth,
2953 bool left_p, bool right_p, XRectangle *clip_rect) 2947 int vwidth, bool left_p, bool right_p, XRectangle *clip_rect)
2954{ 2948{
2955 Display *display = FRAME_X_DISPLAY (s->f); 2949 Display *display = FRAME_X_DISPLAY (s->f);
2956 XGCValues xgcv; 2950 XGCValues xgcv;
@@ -2961,21 +2955,21 @@ x_draw_box_rect (struct glyph_string *s,
2961 2955
2962 /* Top. */ 2956 /* Top. */
2963 x_fill_rectangle (s->f, s->gc, 2957 x_fill_rectangle (s->f, s->gc,
2964 left_x, top_y, right_x - left_x + 1, width); 2958 left_x, top_y, right_x - left_x + 1, hwidth);
2965 2959
2966 /* Left. */ 2960 /* Left. */
2967 if (left_p) 2961 if (left_p)
2968 x_fill_rectangle (s->f, s->gc, 2962 x_fill_rectangle (s->f, s->gc,
2969 left_x, top_y, width, bottom_y - top_y + 1); 2963 left_x, top_y, vwidth, bottom_y - top_y + 1);
2970 2964
2971 /* Bottom. */ 2965 /* Bottom. */
2972 x_fill_rectangle (s->f, s->gc, 2966 x_fill_rectangle (s->f, s->gc,
2973 left_x, bottom_y - width + 1, right_x - left_x + 1, width); 2967 left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth);
2974 2968
2975 /* Right. */ 2969 /* Right. */
2976 if (right_p) 2970 if (right_p)
2977 x_fill_rectangle (s->f, s->gc, 2971 x_fill_rectangle (s->f, s->gc,
2978 right_x - width + 1, top_y, width, bottom_y - top_y + 1); 2972 right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1);
2979 2973
2980 XSetForeground (display, s->gc, xgcv.foreground); 2974 XSetForeground (display, s->gc, xgcv.foreground);
2981 x_reset_clip_rectangles (s->f, s->gc); 2975 x_reset_clip_rectangles (s->f, s->gc);
@@ -2987,7 +2981,7 @@ x_draw_box_rect (struct glyph_string *s,
2987static void 2981static void
2988x_draw_glyph_string_box (struct glyph_string *s) 2982x_draw_glyph_string_box (struct glyph_string *s)
2989{ 2983{
2990 int width, left_x, right_x, top_y, bottom_y, last_x; 2984 int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x;
2991 bool raised_p, left_p, right_p; 2985 bool raised_p, left_p, right_p;
2992 struct glyph *last_glyph; 2986 struct glyph *last_glyph;
2993 XRectangle clip_rect; 2987 XRectangle clip_rect;
@@ -3001,7 +2995,8 @@ x_draw_glyph_string_box (struct glyph_string *s)
3001 ? s->first_glyph 2995 ? s->first_glyph
3002 : s->first_glyph + s->nchars - 1); 2996 : s->first_glyph + s->nchars - 1);
3003 2997
3004 width = eabs (s->face->box_line_width); 2998 vwidth = eabs (s->face->box_vertical_line_width);
2999 hwidth = eabs (s->face->box_horizontal_line_width);
3005 raised_p = s->face->box == FACE_RAISED_BOX; 3000 raised_p = s->face->box == FACE_RAISED_BOX;
3006 left_x = s->x; 3001 left_x = s->x;
3007 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p 3002 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
@@ -3022,13 +3017,13 @@ x_draw_glyph_string_box (struct glyph_string *s)
3022 get_glyph_string_clip_rect (s, &clip_rect); 3017 get_glyph_string_clip_rect (s, &clip_rect);
3023 3018
3024 if (s->face->box == FACE_SIMPLE_BOX) 3019 if (s->face->box == FACE_SIMPLE_BOX)
3025 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, 3020 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth,
3026 left_p, right_p, &clip_rect); 3021 vwidth, left_p, right_p, &clip_rect);
3027 else 3022 else
3028 { 3023 {
3029 x_setup_relief_colors (s); 3024 x_setup_relief_colors (s);
3030 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, 3025 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth,
3031 width, raised_p, true, true, left_p, right_p, 3026 vwidth, raised_p, true, true, left_p, right_p,
3032 &clip_rect); 3027 &clip_rect);
3033 } 3028 }
3034} 3029}
@@ -3086,7 +3081,7 @@ x_draw_image_foreground (struct glyph_string *s)
3086 if (s->face->box != FACE_NO_BOX 3081 if (s->face->box != FACE_NO_BOX
3087 && s->first_glyph->left_box_line_p 3082 && s->first_glyph->left_box_line_p
3088 && s->slice.x == 0) 3083 && s->slice.x == 0)
3089 x += eabs (s->face->box_line_width); 3084 x += max (s->face->box_vertical_line_width, 0);
3090 3085
3091 /* If there is a margin around the image, adjust x- and y-position 3086 /* If there is a margin around the image, adjust x- and y-position
3092 by that margin. */ 3087 by that margin. */
@@ -3205,7 +3200,7 @@ x_draw_image_relief (struct glyph_string *s)
3205 if (s->face->box != FACE_NO_BOX 3200 if (s->face->box != FACE_NO_BOX
3206 && s->first_glyph->left_box_line_p 3201 && s->first_glyph->left_box_line_p
3207 && s->slice.x == 0) 3202 && s->slice.x == 0)
3208 x += eabs (s->face->box_line_width); 3203 x += max (s->face->box_vertical_line_width, 0);
3209 3204
3210 /* If there is a margin around the image, adjust x- and y-position 3205 /* If there is a margin around the image, adjust x- and y-position
3211 by that margin. */ 3206 by that margin. */
@@ -3273,7 +3268,7 @@ x_draw_image_relief (struct glyph_string *s)
3273 3268
3274 x_setup_relief_colors (s); 3269 x_setup_relief_colors (s);
3275 get_glyph_string_clip_rect (s, &r); 3270 get_glyph_string_clip_rect (s, &r);
3276 x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p, 3271 x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p,
3277 top_p, bot_p, left_p, right_p, &r); 3272 top_p, bot_p, left_p, right_p, &r);
3278} 3273}
3279 3274
@@ -3292,7 +3287,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
3292 if (s->face->box != FACE_NO_BOX 3287 if (s->face->box != FACE_NO_BOX
3293 && s->first_glyph->left_box_line_p 3288 && s->first_glyph->left_box_line_p
3294 && s->slice.x == 0) 3289 && s->slice.x == 0)
3295 x += eabs (s->face->box_line_width); 3290 x += max (s->face->box_vertical_line_width, 0);
3296 3291
3297 /* If there is a margin around the image, adjust x- and y-position 3292 /* If there is a margin around the image, adjust x- and y-position
3298 by that margin. */ 3293 by that margin. */
@@ -3394,8 +3389,8 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
3394static void 3389static void
3395x_draw_image_glyph_string (struct glyph_string *s) 3390x_draw_image_glyph_string (struct glyph_string *s)
3396{ 3391{
3397 int box_line_hwidth = eabs (s->face->box_line_width); 3392 int box_line_hwidth = max (s->face->box_vertical_line_width, 0);
3398 int box_line_vwidth = max (s->face->box_line_width, 0); 3393 int box_line_vwidth = max (s->face->box_horizontal_line_width, 0);
3399 int height; 3394 int height;
3400#ifndef USE_CAIRO 3395#ifndef USE_CAIRO
3401 Display *display = FRAME_X_DISPLAY (s->f); 3396 Display *display = FRAME_X_DISPLAY (s->f);