aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGregory Heytings2022-11-24 14:21:30 +0100
committerGregory Heytings2022-11-24 14:21:30 +0100
commitba9315b1641b483f2bf843c38dcdba0cd1643a55 (patch)
treed119cae86c7386db66be72972d90f6c83215974d /src
parentaef803d6c3d61004f15d0bc82fa7bf9952302312 (diff)
parenta3b654e069e563b0a2a6335ec310ada51400ac09 (diff)
downloademacs-ba9315b1641b483f2bf843c38dcdba0cd1643a55.tar.gz
emacs-ba9315b1641b483f2bf843c38dcdba0cd1643a55.zip
Merge master into feature/improved-locked-narrowing.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog.102
-rw-r--r--src/ChangeLog.116
-rw-r--r--src/ChangeLog.128
-rw-r--r--src/ChangeLog.1314
-rw-r--r--src/ChangeLog.52
-rw-r--r--src/ChangeLog.62
-rw-r--r--src/ChangeLog.78
-rw-r--r--src/ChangeLog.86
-rw-r--r--src/alloc.c19
-rw-r--r--src/buffer.c119
-rw-r--r--src/buffer.h1
-rw-r--r--src/callproc.c1
-rw-r--r--src/comp.c4
-rw-r--r--src/dbusbind.c4
-rw-r--r--src/dispextern.h3
-rw-r--r--src/emacs-module.c2
-rw-r--r--src/emacs.c7
-rw-r--r--src/eval.c5
-rw-r--r--src/font.h6
-rw-r--r--src/fontset.c12
-rw-r--r--src/frame.c115
-rw-r--r--src/frame.h1
-rw-r--r--src/ftcrfont.c38
-rw-r--r--src/ftfont.h7
-rw-r--r--src/gnutls.c12
-rw-r--r--src/haiku_support.cc18
-rw-r--r--src/haiku_support.h2
-rw-r--r--src/haikufns.c17
-rw-r--r--src/haikuselect.c2
-rw-r--r--src/haikuterm.c15
-rw-r--r--src/image.c30
-rw-r--r--src/insdel.c57
-rw-r--r--src/itree.c700
-rw-r--r--src/itree.h55
-rw-r--r--src/keyboard.c57
-rw-r--r--src/lisp.h3
-rw-r--r--src/lread.c21
-rw-r--r--src/nsfns.m17
-rw-r--r--src/nsimage.m2
-rw-r--r--src/nsterm.m33
-rw-r--r--src/pdumper.c8
-rw-r--r--src/pgtkfns.c24
-rw-r--r--src/pgtkterm.c257
-rw-r--r--src/pgtkterm.h11
-rw-r--r--src/print.c4
-rw-r--r--src/process.c3
-rw-r--r--src/search.c37
-rw-r--r--src/sqlite.c36
-rw-r--r--src/w32fns.c27
-rw-r--r--src/w32inevt.c2
-rw-r--r--src/xdisp.c62
-rw-r--r--src/xfaces.c20
-rw-r--r--src/xfns.c42
-rw-r--r--src/xselect.c9
-rw-r--r--src/xsettings.c12
-rw-r--r--src/xterm.c889
-rw-r--r--src/xterm.h23
57 files changed, 1911 insertions, 988 deletions
diff --git a/src/ChangeLog.10 b/src/ChangeLog.10
index ba1cea18d4b..1b18ae5ec5d 100644
--- a/src/ChangeLog.10
+++ b/src/ChangeLog.10
@@ -7899,7 +7899,7 @@
7899 * buffer.c (scroll-up-aggressively, scroll-down-aggressively): 7899 * buffer.c (scroll-up-aggressively, scroll-down-aggressively):
7900 * keymap.c (Fminor_mode_key_binding): 7900 * keymap.c (Fminor_mode_key_binding):
7901 * macterm.c (mac-emulate-three-button-mouse): 7901 * macterm.c (mac-emulate-three-button-mouse):
7902 Delete duplicate duplicate words. 7902 Delete duplicate words.
7903 7903
79042005-07-18 Ken Raeburn <raeburn@gnu.org> 79042005-07-18 Ken Raeburn <raeburn@gnu.org>
7905 7905
diff --git a/src/ChangeLog.11 b/src/ChangeLog.11
index 15ab2271718..a00ca453ca4 100644
--- a/src/ChangeLog.11
+++ b/src/ChangeLog.11
@@ -7503,7 +7503,7 @@
75032010-05-28 Kenichi Handa <handa@m17n.org> 75032010-05-28 Kenichi Handa <handa@m17n.org>
7504 7504
7505 * font.c (font_delete_unmatched): Check Vface_ignored_fonts. 7505 * font.c (font_delete_unmatched): Check Vface_ignored_fonts.
7506 Don't sheck SPEC if it is nil. 7506 Don't check SPEC if it is nil.
7507 (font_list_entities): Call font_delete_unmatched if 7507 (font_list_entities): Call font_delete_unmatched if
7508 Vface_ignored_fonts is non-nil. (Bug#6287) 7508 Vface_ignored_fonts is non-nil. (Bug#6287)
7509 7509
@@ -8639,7 +8639,7 @@
8639 8639
8640 * keyboard.c: QClabel is new. 8640 * keyboard.c: QClabel is new.
8641 (parse_tool_bar_item): Take out QClabel from tool bar items. 8641 (parse_tool_bar_item): Take out QClabel from tool bar items.
8642 Try to construct a label if ther is no QClabel. 8642 Try to construct a label if there is no QClabel.
8643 (syms_of_keyboard): Intern :label as QClabel. 8643 (syms_of_keyboard): Intern :label as QClabel.
8644 8644
8645 * dispextern.h (tool_bar_item_idx): TOOL_BAR_ITEM_LABEL is new. 8645 * dispextern.h (tool_bar_item_idx): TOOL_BAR_ITEM_LABEL is new.
@@ -11988,7 +11988,7 @@
11988 11988
11989 * cmds.c (nonundocount): New global variable. 11989 * cmds.c (nonundocount): New global variable.
11990 (keys_of_cmds): Initialize it. 11990 (keys_of_cmds): Initialize it.
11991 (Fself_insert_command): Use it to combine upto 20 sequential chars 11991 (Fself_insert_command): Use it to combine up to 20 sequential chars
11992 into a single undo entry, just like the Qself_insert_command code in 11992 into a single undo entry, just like the Qself_insert_command code in
11993 keyboard.c does. 11993 keyboard.c does.
11994 Call frame_make_pointer_invisible, also like the Qself_insert_command 11994 Call frame_make_pointer_invisible, also like the Qself_insert_command
diff --git a/src/ChangeLog.12 b/src/ChangeLog.12
index 18618bbfb25..7f77c0ca077 100644
--- a/src/ChangeLog.12
+++ b/src/ChangeLog.12
@@ -73,7 +73,7 @@
73 73
74 * lisp.h (adjust_after_replace): Extern it. 74 * lisp.h (adjust_after_replace): Extern it.
75 75
76 * coding.c (detect_coding): Cound the heading ASCII bytes in the 76 * coding.c (detect_coding): Count the heading ASCII bytes in the
77 case of detection for coding_category_utf_8_auto. 77 case of detection for coding_category_utf_8_auto.
78 (decode_coding_gap) [not CODING_DISABLE_ASCII_OPTIMIZATION]: 78 (decode_coding_gap) [not CODING_DISABLE_ASCII_OPTIMIZATION]:
79 Skip decoding if all bytes are ASCII. 79 Skip decoding if all bytes are ASCII.
@@ -1809,7 +1809,7 @@
1809 1809
1810 * nsfns.m (Fns_do_applescript): Run event loop until script has 1810 * nsfns.m (Fns_do_applescript): Run event loop until script has
1811 been executed (Bug#12969). 1811 been executed (Bug#12969).
1812 (ns_run_ascript): Chech as_script for nil, set to nil after 1812 (ns_run_ascript): Check as_script for nil, set to nil after
1813 executing script. 1813 executing script.
1814 1814
18152012-12-22 Martin Rudalics <rudalics@gmx.at> 18152012-12-22 Martin Rudalics <rudalics@gmx.at>
@@ -14132,7 +14132,7 @@
14132 (coding_set_destination): Return how many bytes 14132 (coding_set_destination): Return how many bytes
14133 coding->destination was relocated. 14133 coding->destination was relocated.
14134 (CODING_DECODE_CHAR, CODING_ENCODE_CHAR, CODING_CHAR_CHARSET) 14134 (CODING_DECODE_CHAR, CODING_ENCODE_CHAR, CODING_CHAR_CHARSET)
14135 (CODING_CHAR_CHARSET_P): Adjust for the avove changes. 14135 (CODING_CHAR_CHARSET_P): Adjust for the above changes.
14136 14136
141372011-12-05 Kazuhiro Ito <kzhr@d1.dion.ne.jp> (tiny change) 141372011-12-05 Kazuhiro Ito <kzhr@d1.dion.ne.jp> (tiny change)
14138 14138
@@ -19967,7 +19967,7 @@
199672011-05-05 Eli Zaretskii <eliz@gnu.org> 199672011-05-05 Eli Zaretskii <eliz@gnu.org>
19968 19968
19969 * w32heap.c (allocate_heap) [USE_LISP_UNION_TYPE || USE_LSB_TAG]: 19969 * w32heap.c (allocate_heap) [USE_LISP_UNION_TYPE || USE_LSB_TAG]:
19970 New version that can reserve upto 2GB of heap space. 19970 New version that can reserve up to 2GB of heap space.
19971 19971
199722011-05-05 Chong Yidong <cyd@stupidchicken.com> 199722011-05-05 Chong Yidong <cyd@stupidchicken.com>
19973 19973
diff --git a/src/ChangeLog.13 b/src/ChangeLog.13
index 268a59219c4..91f8005ac51 100644
--- a/src/ChangeLog.13
+++ b/src/ChangeLog.13
@@ -1459,11 +1459,11 @@
1459 (frame_default_tool_bar_height): Extern. 1459 (frame_default_tool_bar_height): Extern.
1460 * gtkutil.c (xg_frame_set_char_size): Pass Qxg_frame_set_char_size 1460 * gtkutil.c (xg_frame_set_char_size): Pass Qxg_frame_set_char_size
1461 to adjust_frame_size. 1461 to adjust_frame_size.
1462 * nsfns.m (Fx_create_frame): Pass Pass Qx_create_frame_1 and 1462 * nsfns.m (Fx_create_frame): Pass Qx_create_frame_1 and
1463 Qx_create_frame_2 to adjust_frame_size. 1463 Qx_create_frame_2 to adjust_frame_size.
1464 * w32fns.c (x_change_tool_bar_height): Call adjust_frame_size with 1464 * w32fns.c (x_change_tool_bar_height): Call adjust_frame_size with
1465 inhibit 1 when we have not redisplayed the tool bar yet. 1465 inhibit 1 when we have not redisplayed the tool bar yet.
1466 (Fx_create_frame): Pass Pass Qx_create_frame_1 and 1466 (Fx_create_frame): Pass Qx_create_frame_1 and
1467 Qx_create_frame_2 to adjust_frame_size. 1467 Qx_create_frame_2 to adjust_frame_size.
1468 * w32menu.c (set_frame_menubar): Simplify adjust_frame_size 1468 * w32menu.c (set_frame_menubar): Simplify adjust_frame_size
1469 call. 1469 call.
@@ -1476,7 +1476,7 @@
1476 frame size accordingly. 1476 frame size accordingly.
1477 * xfns.c (x_change_tool_bar_height): Call adjust_frame_size with 1477 * xfns.c (x_change_tool_bar_height): Call adjust_frame_size with
1478 inhibit 1 when we have not redisplayed the tool bar yet. 1478 inhibit 1 when we have not redisplayed the tool bar yet.
1479 (Fx_create_frame): Pass Pass Qx_create_frame_1 and 1479 (Fx_create_frame): Pass Qx_create_frame_1 and
1480 Qx_create_frame_2 to adjust_frame_size. 1480 Qx_create_frame_2 to adjust_frame_size.
1481 1481
14822015-01-12 Paul Eggert <eggert@cs.ucla.edu> 14822015-01-12 Paul Eggert <eggert@cs.ucla.edu>
@@ -7498,7 +7498,7 @@
74982014-04-16 Eli Zaretskii <eliz@gnu.org> 74982014-04-16 Eli Zaretskii <eliz@gnu.org>
7499 7499
7500 * insdel.c (invalidate_buffer_caches): When deleting or replacing 7500 * insdel.c (invalidate_buffer_caches): When deleting or replacing
7501 text, invalidate the bidi_paragraph_cache upto and including the 7501 text, invalidate the bidi_paragraph_cache up to and including the
7502 preceding newline. 7502 preceding newline.
7503 7503
75042014-04-16 Paul Eggert <eggert@cs.ucla.edu> 75042014-04-16 Paul Eggert <eggert@cs.ucla.edu>
@@ -10183,7 +10183,7 @@
10183 (w32_wnd_proc): Handle bottom divider width. 10183 (w32_wnd_proc): Handle bottom divider width.
10184 For WM_WINDOWPOSCHANGING return zero if we resize pixelwise. 10184 For WM_WINDOWPOSCHANGING return zero if we resize pixelwise.
10185 (Fx_create_frame): Default divider width parameters. 10185 (Fx_create_frame): Default divider width parameters.
10186 Caclulate sizes pixelwise. Add vertical drag cursor support. 10186 Calculate sizes pixelwise. Add vertical drag cursor support.
10187 (x_create_tip_frame): Default divider widths to zero. 10187 (x_create_tip_frame): Default divider widths to zero.
10188 Pixelize call to change_frame_size. 10188 Pixelize call to change_frame_size.
10189 (Fx_show_tip): Add handling of divider widths. Pixelize window 10189 (Fx_show_tip): Add handling of divider widths. Pixelize window
@@ -10868,7 +10868,7 @@
10868 10868
10869 * xdisp.c (syms_of_xdisp): New vars redisplay--all-windows-cause and 10869 * xdisp.c (syms_of_xdisp): New vars redisplay--all-windows-cause and
10870 redisplay--mode-lines-cause. 10870 redisplay--mode-lines-cause.
10871 (redisplay_internal): Keep them uptodate. Remove redundant check of 10871 (redisplay_internal): Keep them up-to-date. Remove redundant check of
10872 buffer_shared_and_changed. 10872 buffer_shared_and_changed.
10873 * *.[chm]: Number every assignment to update_mode_lines so we 10873 * *.[chm]: Number every assignment to update_mode_lines so we
10874 can track why it is set. 10874 can track why it is set.
@@ -12566,7 +12566,7 @@
125662013-09-16 Dmitry Antipov <dmantipov@yandex.ru> 125662013-09-16 Dmitry Antipov <dmantipov@yandex.ru>
12567 12567
12568 Do not copy X event in handle_one_xevent except KeyPress case. 12568 Do not copy X event in handle_one_xevent except KeyPress case.
12569 Wnen XEvent is processed, it is unlikely to be changed except 12569 When XEvent is processed, it is unlikely to be changed except
12570 KeyPress case, so we can avoid copying and use const pointer to 12570 KeyPress case, so we can avoid copying and use const pointer to
12571 const data to make sure that an event is not changed elsewhere. 12571 const data to make sure that an event is not changed elsewhere.
12572 * xterm.c (handle_one_xevent): Change 2nd arg to 'const XEvent * 12572 * xterm.c (handle_one_xevent): Change 2nd arg to 'const XEvent *
diff --git a/src/ChangeLog.5 b/src/ChangeLog.5
index c74e44d7a2f..408a934ce2e 100644
--- a/src/ChangeLog.5
+++ b/src/ChangeLog.5
@@ -2316,7 +2316,7 @@
2316 2316
23171995-02-15 Paul Reilly <pmr@geech.gnu.ai.mit.edu> 23171995-02-15 Paul Reilly <pmr@geech.gnu.ai.mit.edu>
2318 2318
2319 * s/dgux.h (LIB_MOTIF): Add -lgen to provide provide the symbols 2319 * s/dgux.h (LIB_MOTIF): Add -lgen to provide the symbols
2320 `regcmp' and `regex'. 2320 `regcmp' and `regex'.
2321 2321
23221995-02-15 Richard Stallman <rms@pogo.gnu.ai.mit.edu> 23221995-02-15 Richard Stallman <rms@pogo.gnu.ai.mit.edu>
diff --git a/src/ChangeLog.6 b/src/ChangeLog.6
index fc7cc5e4d48..f5653efd91e 100644
--- a/src/ChangeLog.6
+++ b/src/ChangeLog.6
@@ -2225,7 +2225,7 @@
2225 2225
22261996-02-08 Eli Zaretskii <eliz@is.elta.co.il> 22261996-02-08 Eli Zaretskii <eliz@is.elta.co.il>
2227 2227
2228 * fileio.c (Fmake_temp_name) [MS-DOS]: Allow upto 8 characters in 2228 * fileio.c (Fmake_temp_name) [MS-DOS]: Allow up to 8 characters in
2229 the prefix of the temporary file name. 2229 the prefix of the temporary file name.
2230 2230
22311996-02-07 Richard Stallman <rms@mole.gnu.ai.mit.edu> 22311996-02-07 Richard Stallman <rms@mole.gnu.ai.mit.edu>
diff --git a/src/ChangeLog.7 b/src/ChangeLog.7
index e893a2a6d82..9c6fd810d34 100644
--- a/src/ChangeLog.7
+++ b/src/ChangeLog.7
@@ -1215,19 +1215,19 @@
1215 1215
1216 * ccl.c: Change term translation to code conversion, then change 1216 * ccl.c: Change term translation to code conversion, then change
1217 terms unify/unification to translate/translation respectively 1217 terms unify/unification to translate/translation respectively
1218 throughtout the file. 1218 throughout the file.
1219 1219
1220 * charset.c: Change terms unify/unification to 1220 * charset.c: Change terms unify/unification to
1221 translate/translation respectively throughtout the file. 1221 translate/translation respectively throughout the file.
1222 (ONE_BYTE_CHAR_WIDTH): Delete unnecessary continuation line at the 1222 (ONE_BYTE_CHAR_WIDTH): Delete unnecessary continuation line at the
1223 tail. 1223 tail.
1224 1224
1225 * charset.h: Change terms unify/unification to 1225 * charset.h: Change terms unify/unification to
1226 translate/translation respectively throughtout the file. 1226 translate/translation respectively throughout the file.
1227 (GET_TRANSLATION_TABLE): Name changed from UNIFICATION_ID_TABLE. 1227 (GET_TRANSLATION_TABLE): Name changed from UNIFICATION_ID_TABLE.
1228 1228
1229 * coding.c: Change terms unify/unification to 1229 * coding.c: Change terms unify/unification to
1230 translate/translation respectively throughtout the file. 1230 translate/translation respectively throughout the file.
1231 (encode_coding_iso2022): Fix bug in encoding a text ending by a 1231 (encode_coding_iso2022): Fix bug in encoding a text ending by a
1232 composite character. 1232 composite character.
1233 (check_composing_code): If we are decoding the last block of data, 1233 (check_composing_code): If we are decoding the last block of data,
diff --git a/src/ChangeLog.8 b/src/ChangeLog.8
index ef2472a0f33..c0e3523c648 100644
--- a/src/ChangeLog.8
+++ b/src/ChangeLog.8
@@ -1272,7 +1272,7 @@
1272 1272
1273 * xdisp.c (display_line): Set charpos of first glyph in blank 1273 * xdisp.c (display_line): Set charpos of first glyph in blank
1274 lines not corresponding to any text to -1, even if no glyphs are 1274 lines not corresponding to any text to -1, even if no glyphs are
1275 filled in in that line. 1275 filled in on that line.
1276 1276
12771999-11-01 Gerd Moellmann <gerd@gnu.org> 12771999-11-01 Gerd Moellmann <gerd@gnu.org>
1278 1278
@@ -3155,7 +3155,7 @@
3155 3155
3156 * xdisp.c (resize_mini_window): Don't resize if 3156 * xdisp.c (resize_mini_window): Don't resize if
3157 Vmax_mini_window_height is nil. Otherwise, use a default if 3157 Vmax_mini_window_height is nil. Otherwise, use a default if
3158 Vmax_mini_window_height is not ot a number. 3158 Vmax_mini_window_height is not a number.
3159 (syms_of_xdisp): Extend documentation of Vmax_mini_window_height. 3159 (syms_of_xdisp): Extend documentation of Vmax_mini_window_height.
3160 3160
31611999-08-25 Alexandre Oliva <oliva@dcc.unicamp.br> 31611999-08-25 Alexandre Oliva <oliva@dcc.unicamp.br>
@@ -5704,7 +5704,7 @@
5704 (x_scroll_bar_expose): Make no-op for toolkit scroll bars. 5704 (x_scroll_bar_expose): Make no-op for toolkit scroll bars.
5705 (x_scroll_bar_create): Create and show a scroll bar widget 5705 (x_scroll_bar_create): Create and show a scroll bar widget
5706 if using toolkit scroll bars. 5706 if using toolkit scroll bars.
5707 (x_scroll_bar_move): Handle tookit scroll bars. 5707 (x_scroll_bar_move): Handle toolkit scroll bars.
5708 5708
5709 * Makefile.in (LIBW): Use Xaw3d if present. 5709 * Makefile.in (LIBW): Use Xaw3d if present.
5710 5710
diff --git a/src/alloc.c b/src/alloc.c
index f69c65dedc1..d3f696d5ade 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6279,11 +6279,6 @@ garbage_collect (void)
6279 image_prune_animation_caches (false); 6279 image_prune_animation_caches (false);
6280#endif 6280#endif
6281 6281
6282 /* ELisp code run by `gc-post-hook' could result in itree iteration,
6283 which must not happen while the itree is already busy. See
6284 bug#58639. */
6285 eassert (!itree_iterator_busy_p ());
6286
6287 if (!NILP (Vpost_gc_hook)) 6282 if (!NILP (Vpost_gc_hook))
6288 { 6283 {
6289 specpdl_ref gc_count = inhibit_garbage_collection (); 6284 specpdl_ref gc_count = inhibit_garbage_collection ();
@@ -6508,7 +6503,7 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype)
6508static void 6503static void
6509mark_overlay (struct Lisp_Overlay *ov) 6504mark_overlay (struct Lisp_Overlay *ov)
6510{ 6505{
6511 /* We don't mark the `interval_node` object, because it is managed manually 6506 /* We don't mark the `itree_node` object, because it is managed manually
6512 rather than by the GC. */ 6507 rather than by the GC. */
6513 eassert (BASE_EQ (ov->interval->data, make_lisp_ptr (ov, Lisp_Vectorlike))); 6508 eassert (BASE_EQ (ov->interval->data, make_lisp_ptr (ov, Lisp_Vectorlike)));
6514 set_vectorlike_marked (&ov->header); 6509 set_vectorlike_marked (&ov->header);
@@ -7780,13 +7775,23 @@ allocated since the last garbage collection. All data types count.
7780Garbage collection happens automatically only when `eval' is called. 7775Garbage collection happens automatically only when `eval' is called.
7781 7776
7782By binding this temporarily to a large number, you can effectively 7777By binding this temporarily to a large number, you can effectively
7783prevent garbage collection during a part of the program. 7778prevent garbage collection during a part of the program. But be
7779sure to get back to the normal value soon enough, to avoid system-wide
7780memory pressure, and never use a too-high value for prolonged periods
7781of time.
7784See also `gc-cons-percentage'. */); 7782See also `gc-cons-percentage'. */);
7785 7783
7786 DEFVAR_LISP ("gc-cons-percentage", Vgc_cons_percentage, 7784 DEFVAR_LISP ("gc-cons-percentage", Vgc_cons_percentage,
7787 doc: /* Portion of the heap used for allocation. 7785 doc: /* Portion of the heap used for allocation.
7788Garbage collection can happen automatically once this portion of the heap 7786Garbage collection can happen automatically once this portion of the heap
7789has been allocated since the last garbage collection. 7787has been allocated since the last garbage collection.
7788
7789By binding this temporarily to a large number, you can effectively
7790prevent garbage collection during a part of the program. But be
7791sure to get back to the normal value soon enough, to avoid system-wide
7792memory pressure, and never use a too-high value for prolonged periods
7793of time.
7794
7790If this portion is smaller than `gc-cons-threshold', this is ignored. */); 7795If this portion is smaller than `gc-cons-threshold', this is ignored. */);
7791 Vgc_cons_percentage = make_float (0.1); 7796 Vgc_cons_percentage = make_float (0.1);
7792 7797
diff --git a/src/buffer.c b/src/buffer.c
index b67b989326e..d948aaa2662 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -937,19 +937,16 @@ delete_all_overlays (struct buffer *b)
937 if (! b->overlays) 937 if (! b->overlays)
938 return; 938 return;
939 939
940 /* FIXME: This loop sets the overlays' `buffer` field to NULL but 940 /* The general rule is that the tree cannot be modified from within
941 doesn't set the itree_nodes' `parent`, `left` and `right` 941 ITREE_FOREACH, but here we bend this rule a little because we know
942 fields accordingly. I believe it's harmless, but a bit untidy since 942 that the POST_ORDER iterator will not need to look at `node` again. */
943 other parts of the code are careful to set those fields to NULL when 943 ITREE_FOREACH (node, b->overlays, PTRDIFF_MIN, PTRDIFF_MAX, POST_ORDER)
944 the overlay is deleted.
945 Of course, we can't set them to NULL from within the iteration
946 because the iterator may need them (tho we could if we added
947 an ITREE_POST_ORDER iteration order). */
948 ITREE_FOREACH (node, b->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING)
949 { 944 {
950 modify_overlay (b, node->begin, node->end); 945 modify_overlay (b, node->begin, node->end);
951 /* Where are the nodes freed ? --ap */
952 XOVERLAY (node->data)->buffer = NULL; 946 XOVERLAY (node->data)->buffer = NULL;
947 node->parent = NULL;
948 node->left = NULL;
949 node->right = NULL;
953 } 950 }
954 itree_clear (b->overlays); 951 itree_clear (b->overlays);
955} 952}
@@ -982,7 +979,7 @@ set_overlays_multibyte (bool multibyte)
982 struct itree_tree *tree = current_buffer->overlays; 979 struct itree_tree *tree = current_buffer->overlays;
983 const intmax_t size = itree_size (tree); 980 const intmax_t size = itree_size (tree);
984 981
985 /* We can't use `interval_node_set_region` at the same time 982 /* We can't use `itree_node_set_region` at the same time
986 as we iterate over the itree, so we need an auxiliary storage 983 as we iterate over the itree, so we need an auxiliary storage
987 to keep the list of nodes. */ 984 to keep the list of nodes. */
988 USE_SAFE_ALLOCA; 985 USE_SAFE_ALLOCA;
@@ -2985,17 +2982,13 @@ overlays_in (ptrdiff_t beg, ptrdiff_t end, bool extend,
2985 if (node->begin > end) 2982 if (node->begin > end)
2986 { 2983 {
2987 next = min (next, node->begin); 2984 next = min (next, node->begin);
2988 ITREE_FOREACH_ABORT ();
2989 break; 2985 break;
2990 } 2986 }
2991 else if (node->begin == end) 2987 else if (node->begin == end)
2992 { 2988 {
2993 next = node->begin; 2989 next = node->begin;
2994 if ((! empty || end < ZV) && beg < end) 2990 if ((! empty || end < ZV) && beg < end)
2995 { 2991 break;
2996 ITREE_FOREACH_ABORT ();
2997 break;
2998 }
2999 if (empty && node->begin != node->end) 2992 if (empty && node->begin != node->end)
3000 continue; 2993 continue;
3001 } 2994 }
@@ -3050,7 +3043,6 @@ next_overlay_change (ptrdiff_t pos)
3050 of pos, because the search is limited to [pos,next) . */ 3043 of pos, because the search is limited to [pos,next) . */
3051 eassert (node->begin < next); 3044 eassert (node->begin < next);
3052 next = node->begin; 3045 next = node->begin;
3053 ITREE_FOREACH_ABORT ();
3054 break; 3046 break;
3055 } 3047 }
3056 else if (node->begin < node->end && node->end < next) 3048 else if (node->begin < node->end && node->end < next)
@@ -3155,10 +3147,7 @@ overlay_touches_p (ptrdiff_t pos)
3155 pos. */ 3147 pos. */
3156 ITREE_FOREACH (node, current_buffer->overlays, pos - 1, pos + 1, DESCENDING) 3148 ITREE_FOREACH (node, current_buffer->overlays, pos - 1, pos + 1, DESCENDING)
3157 if (node->begin == pos || node->end == pos) 3149 if (node->begin == pos || node->end == pos)
3158 { 3150 return true;
3159 ITREE_FOREACH_ABORT ();
3160 return true;
3161 }
3162 return false; 3151 return false;
3163} 3152}
3164 3153
@@ -3454,21 +3443,66 @@ overlay_strings (ptrdiff_t pos, struct window *w, unsigned char **pstr)
3454 3443
3455 3444
3456void 3445void
3457adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length) 3446adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length, bool before_markers)
3458{ 3447{
3459 /* After an insertion, the lists are still sorted properly, 3448 if (!current_buffer->indirections)
3460 but we may need to update the value of the overlay center. */ 3449 itree_insert_gap (current_buffer->overlays, pos, length, before_markers);
3461 if (! current_buffer->overlays) 3450 else
3462 return; 3451 {
3463 itree_insert_gap (current_buffer->overlays, pos, length); 3452 struct buffer *base = current_buffer->base_buffer
3453 ? current_buffer->base_buffer
3454 : current_buffer;
3455 Lisp_Object tail, other;
3456 itree_insert_gap (base->overlays, pos, length, before_markers);
3457 FOR_EACH_LIVE_BUFFER (tail, other)
3458 if (XBUFFER (other)->base_buffer == base)
3459 itree_insert_gap (XBUFFER (other)->overlays, pos, length,
3460 before_markers);
3461 }
3462}
3463
3464static void
3465adjust_overlays_for_delete_in_buffer (struct buffer * buf,
3466 ptrdiff_t pos, ptrdiff_t length)
3467{
3468 Lisp_Object hit_list = Qnil;
3469 struct itree_node *node;
3470
3471 /* Ideally, the evaporate check would be done directly within
3472 `itree_delete_gap`, but that code isn't supposed to know about overlays,
3473 only about `itree_node`s, so it would break an abstraction boundary. */
3474 itree_delete_gap (buf->overlays, pos, length);
3475
3476 /* Delete any zero-sized overlays at position POS, if the `evaporate'
3477 property is set. */
3478
3479 ITREE_FOREACH (node, buf->overlays, pos, pos, ASCENDING)
3480 {
3481 if (node->end == pos && node->begin == pos
3482 && ! NILP (Foverlay_get (node->data, Qevaporate)))
3483 hit_list = Fcons (node->data, hit_list);
3484 }
3485
3486 for (; CONSP (hit_list); hit_list = XCDR (hit_list))
3487 Fdelete_overlay (XCAR (hit_list));
3464} 3488}
3465 3489
3466void 3490void
3467adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length) 3491adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length)
3468{ 3492{
3469 if (! current_buffer->overlays) 3493 if (!current_buffer->indirections)
3470 return; 3494 adjust_overlays_for_delete_in_buffer (current_buffer, pos, length);
3471 itree_delete_gap (current_buffer->overlays, pos, length); 3495 else
3496 {
3497 struct buffer *base = current_buffer->base_buffer
3498 ? current_buffer->base_buffer
3499 : current_buffer;
3500 Lisp_Object tail, other;
3501 adjust_overlays_for_delete_in_buffer (base, pos, length);
3502 FOR_EACH_LIVE_BUFFER (tail, other)
3503 if (XBUFFER (other)->base_buffer == base)
3504 adjust_overlays_for_delete_in_buffer (XBUFFER (other), pos, length);
3505 }
3472} 3506}
3473 3507
3474 3508
@@ -3601,7 +3635,7 @@ buffer. */)
3601 o_end = OVERLAY_END (overlay); 3635 o_end = OVERLAY_END (overlay);
3602 } 3636 }
3603 3637
3604 if (! EQ (buffer, obuffer)) 3638 if (! BASE_EQ (buffer, obuffer))
3605 { 3639 {
3606 if (! NILP (obuffer)) 3640 if (! NILP (obuffer))
3607 remove_buffer_overlay (XBUFFER (obuffer), XOVERLAY (overlay)); 3641 remove_buffer_overlay (XBUFFER (obuffer), XOVERLAY (overlay));
@@ -3790,7 +3824,9 @@ and also contained within the specified region.
3790 3824
3791Empty overlays are included in the result if they are located at BEG, 3825Empty overlays are included in the result if they are located at BEG,
3792between BEG and END, or at END provided END denotes the position at the 3826between BEG and END, or at END provided END denotes the position at the
3793end of the accessible part of the buffer. */) 3827end of the accessible part of the buffer.
3828
3829The resulting list of overlays is in an arbitrary unpredictable order. */)
3794 (Lisp_Object beg, Lisp_Object end) 3830 (Lisp_Object beg, Lisp_Object end)
3795{ 3831{
3796 ptrdiff_t len, noverlays; 3832 ptrdiff_t len, noverlays;
@@ -4080,25 +4116,6 @@ call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, bool after,
4080 } 4116 }
4081} 4117}
4082 4118
4083/* Delete any zero-sized overlays at position POS, if the `evaporate'
4084 property is set. */
4085void
4086evaporate_overlays (ptrdiff_t pos)
4087{
4088 Lisp_Object hit_list = Qnil;
4089 struct itree_node *node;
4090
4091 ITREE_FOREACH (node, current_buffer->overlays, pos, pos, ASCENDING)
4092 {
4093 if (node->end == pos
4094 && ! NILP (Foverlay_get (node->data, Qevaporate)))
4095 hit_list = Fcons (node->data, hit_list);
4096 }
4097
4098 for (; CONSP (hit_list); hit_list = XCDR (hit_list))
4099 Fdelete_overlay (XCAR (hit_list));
4100}
4101
4102/*********************************************************************** 4119/***********************************************************************
4103 Allocation with mmap 4120 Allocation with mmap
4104 ***********************************************************************/ 4121 ***********************************************************************/
diff --git a/src/buffer.h b/src/buffer.h
index 3ea4125645d..2e80c8a7b04 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1170,7 +1170,6 @@ extern EMACS_INT fix_position (Lisp_Object);
1170extern void delete_all_overlays (struct buffer *); 1170extern void delete_all_overlays (struct buffer *);
1171extern void reset_buffer (struct buffer *); 1171extern void reset_buffer (struct buffer *);
1172extern void compact_buffer (struct buffer *); 1172extern void compact_buffer (struct buffer *);
1173extern void evaporate_overlays (ptrdiff_t);
1174extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); 1173extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *);
1175extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **, 1174extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **,
1176 ptrdiff_t *, bool, bool, ptrdiff_t *); 1175 ptrdiff_t *, bool, bool, ptrdiff_t *);
diff --git a/src/callproc.c b/src/callproc.c
index 4d4b86629cf..f9f840e5440 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -648,6 +648,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
648 648
649#ifndef MSDOS 649#ifndef MSDOS
650 650
651 child_signal_init ();
651 block_input (); 652 block_input ();
652 block_child_signal (&oldset); 653 block_child_signal (&oldset);
653 654
diff --git a/src/comp.c b/src/comp.c
index 14012634ccc..b6072a866e6 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -947,7 +947,7 @@ obj_to_reloc (Lisp_Object obj)
947 } 947 }
948 948
949 xsignal1 (Qnative_ice, 949 xsignal1 (Qnative_ice,
950 build_string ("cant't find data in relocation containers")); 950 build_string ("can't find data in relocation containers"));
951 assume (false); 951 assume (false);
952 952
953 found: 953 found:
@@ -5609,7 +5609,7 @@ file_in_eln_sys_dir (Lisp_Object filename)
5609/* Load related routines. */ 5609/* Load related routines. */
5610DEFUN ("native-elisp-load", Fnative_elisp_load, Snative_elisp_load, 1, 2, 0, 5610DEFUN ("native-elisp-load", Fnative_elisp_load, Snative_elisp_load, 1, 2, 0,
5611 doc: /* Load native elisp code FILENAME. 5611 doc: /* Load native elisp code FILENAME.
5612LATE_LOAD has to be non-nil when loading for deferred compilation. */) 5612LATE-LOAD has to be non-nil when loading for deferred compilation. */)
5613 (Lisp_Object filename, Lisp_Object late_load) 5613 (Lisp_Object filename, Lisp_Object late_load)
5614{ 5614{
5615 CHECK_STRING (filename); 5615 CHECK_STRING (filename);
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 1c74180f15c..440142757ec 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -422,7 +422,7 @@ xd_signature (char *signature, int dtype, int parent_type, Lisp_Object object)
422 case DBUS_TYPE_STRING: 422 case DBUS_TYPE_STRING:
423 case DBUS_TYPE_OBJECT_PATH: 423 case DBUS_TYPE_OBJECT_PATH:
424 case DBUS_TYPE_SIGNATURE: 424 case DBUS_TYPE_SIGNATURE:
425 /* We dont check the syntax of signature. This will be done by 425 /* We don't check the syntax of signature. This will be done by
426 libdbus. */ 426 libdbus. */
427 if (dtype == DBUS_TYPE_OBJECT_PATH) 427 if (dtype == DBUS_TYPE_OBJECT_PATH)
428 XD_DBUS_VALIDATE_PATH (object) 428 XD_DBUS_VALIDATE_PATH (object)
@@ -748,7 +748,7 @@ xd_append_arg (int dtype, Lisp_Object object, DBusMessageIter *iter)
748 case DBUS_TYPE_STRING: 748 case DBUS_TYPE_STRING:
749 case DBUS_TYPE_OBJECT_PATH: 749 case DBUS_TYPE_OBJECT_PATH:
750 case DBUS_TYPE_SIGNATURE: 750 case DBUS_TYPE_SIGNATURE:
751 /* We dont check the syntax of signature. This will be done 751 /* We don't check the syntax of signature. This will be done
752 by libdbus. */ 752 by libdbus. */
753 if (dtype == DBUS_TYPE_OBJECT_PATH) 753 if (dtype == DBUS_TYPE_OBJECT_PATH)
754 XD_DBUS_VALIDATE_PATH (object) 754 XD_DBUS_VALIDATE_PATH (object)
diff --git a/src/dispextern.h b/src/dispextern.h
index 2f5f4335fe5..2afbdeabaab 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3495,7 +3495,8 @@ extern bool cursor_in_mouse_face_p (struct window *w);
3495extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *, 3495extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *,
3496 int, int, enum draw_glyphs_face); 3496 int, int, enum draw_glyphs_face);
3497extern void display_tty_menu_item (const char *, int, int, int, int, bool); 3497extern void display_tty_menu_item (const char *, int, int, int, int, bool);
3498 3498extern struct glyph *x_y_to_hpos_vpos (struct window *, int, int, int *, int *,
3499 int *, int *, int *);
3499/* Flags passed to try_window. */ 3500/* Flags passed to try_window. */
3500#define TRY_WINDOW_CHECK_MARGINS (1 << 0) 3501#define TRY_WINDOW_CHECK_MARGINS (1 << 0)
3501#define TRY_WINDOW_IGNORE_FONTS_CHANGE (1 << 1) 3502#define TRY_WINDOW_IGNORE_FONTS_CHANGE (1 << 1)
diff --git a/src/emacs-module.c b/src/emacs-module.c
index fcdf103c19b..35d6e9e0d7a 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -561,7 +561,7 @@ static struct Lisp_Module_Function *
561allocate_module_function (void) 561allocate_module_function (void)
562{ 562{
563 return ALLOCATE_PSEUDOVECTOR (struct Lisp_Module_Function, 563 return ALLOCATE_PSEUDOVECTOR (struct Lisp_Module_Function,
564 interactive_form, PVEC_MODULE_FUNCTION); 564 command_modes, PVEC_MODULE_FUNCTION);
565} 565}
566 566
567#define XSET_MODULE_FUNCTION(var, ptr) \ 567#define XSET_MODULE_FUNCTION(var, ptr) \
diff --git a/src/emacs.c b/src/emacs.c
index 8ad70fecd41..85102acd28e 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -82,6 +82,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
82#endif /* HAVE_WINDOW_SYSTEM */ 82#endif /* HAVE_WINDOW_SYSTEM */
83 83
84#include "bignum.h" 84#include "bignum.h"
85#include "itree.h"
85#include "intervals.h" 86#include "intervals.h"
86#include "character.h" 87#include "character.h"
87#include "buffer.h" 88#include "buffer.h"
@@ -431,9 +432,9 @@ terminate_due_to_signal (int sig, int backtrace_limit)
431 if (sig == SIGTERM || sig == SIGHUP || sig == SIGINT) 432 if (sig == SIGTERM || sig == SIGHUP || sig == SIGINT)
432 { 433 {
433 /* Avoid abort in shut_down_emacs if we were interrupted 434 /* Avoid abort in shut_down_emacs if we were interrupted
434 by SIGINT in noninteractive usage, as in that case we 435 in noninteractive usage, as in that case we don't
435 don't care about the message stack. */ 436 care about the message stack. */
436 if (sig == SIGINT && noninteractive) 437 if (noninteractive)
437 clear_message_stack (); 438 clear_message_stack ();
438 Fkill_emacs (make_fixnum (sig), Qnil); 439 Fkill_emacs (make_fixnum (sig), Qnil);
439 } 440 }
diff --git a/src/eval.c b/src/eval.c
index ea238299488..7327d681f9a 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1329,7 +1329,7 @@ Then the value of the last BODY form is returned from the `condition-case'
1329expression. 1329expression.
1330 1330
1331The special handler (:success BODY...) is invoked if BODYFORM terminated 1331The special handler (:success BODY...) is invoked if BODYFORM terminated
1332without signalling an error. BODY is then evaluated with VAR bound to 1332without signaling an error. BODY is then evaluated with VAR bound to
1333the value returned by BODYFORM. 1333the value returned by BODYFORM.
1334 1334
1335See also the function `signal' for more info. 1335See also the function `signal' for more info.
@@ -1716,7 +1716,6 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
1716 Lisp_Object clause = Qnil; 1716 Lisp_Object clause = Qnil;
1717 struct handler *h; 1717 struct handler *h;
1718 1718
1719 eassert (!itree_iterator_busy_p ());
1720 if (gc_in_progress || waiting_for_input) 1719 if (gc_in_progress || waiting_for_input)
1721 emacs_abort (); 1720 emacs_abort ();
1722 1721
@@ -1810,7 +1809,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
1810 unbind_to (count, Qnil); 1809 unbind_to (count, Qnil);
1811 } 1810 }
1812 1811
1813 /* If an error is signalled during a Lisp hook in redisplay, write a 1812 /* If an error is signaled during a Lisp hook in redisplay, write a
1814 backtrace into the buffer *Redisplay-trace*. */ 1813 backtrace into the buffer *Redisplay-trace*. */
1815 if (!debugger_called && !NILP (error_symbol) 1814 if (!debugger_called && !NILP (error_symbol)
1816 && backtrace_on_redisplay_error 1815 && backtrace_on_redisplay_error
diff --git a/src/font.h b/src/font.h
index 3475189206f..d36c45a53c4 100644
--- a/src/font.h
+++ b/src/font.h
@@ -220,13 +220,13 @@ enum font_property_index
220#define FONT_WIDTH_FOR_FACE(font) \ 220#define FONT_WIDTH_FOR_FACE(font) \
221 font_style_symbolic (font, FONT_WIDTH_INDEX, true) 221 font_style_symbolic (font, FONT_WIDTH_INDEX, true)
222 222
223/* Return the numeric weight value corresponding ot the symbol NAME. */ 223/* Return the numeric weight value corresponding to the symbol NAME. */
224#define FONT_WEIGHT_NAME_NUMERIC(name) \ 224#define FONT_WEIGHT_NAME_NUMERIC(name) \
225 (font_style_to_value (FONT_WEIGHT_INDEX, (name), false) >> 8) 225 (font_style_to_value (FONT_WEIGHT_INDEX, (name), false) >> 8)
226/* Return the numeric slant value corresponding ot the symbol NAME. */ 226/* Return the numeric slant value corresponding to the symbol NAME. */
227#define FONT_SLANT_NAME_NUMERIC(name) \ 227#define FONT_SLANT_NAME_NUMERIC(name) \
228 (font_style_to_value (FONT_SLANT_INDEX, (name), false) >> 8) 228 (font_style_to_value (FONT_SLANT_INDEX, (name), false) >> 8)
229/* Return the numeric width value corresponding ot the symbol NAME. */ 229/* Return the numeric width value corresponding to the symbol NAME. */
230#define FONT_WIDTH_NAME_NUMERIC(name) \ 230#define FONT_WIDTH_NAME_NUMERIC(name) \
231 (font_style_to_value (FONT_WIDTH_INDEX, (name), false) >> 8) 231 (font_style_to_value (FONT_WIDTH_INDEX, (name), false) >> 8)
232 232
diff --git a/src/fontset.c b/src/fontset.c
index 4b91eff2ef6..b82737d005a 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1663,7 +1663,17 @@ overwrites the previous settings. */)
1663 { 1663 {
1664 update_auto_fontset_alist (font_object, fontset_obj); 1664 update_auto_fontset_alist (font_object, fontset_obj);
1665 AUTO_FRAME_ARG (arg, Qfont, Fcons (fontset, font_object)); 1665 AUTO_FRAME_ARG (arg, Qfont, Fcons (fontset, font_object));
1666 Fmodify_frame_parameters (fr, arg); 1666
1667#ifdef HAVE_WINDOW_SYSTEM
1668 if (FRAME_WINDOW_P (f))
1669 /* This is a window-system frame. Prevent changes of
1670 the `font' parameter here from messing with the
1671 `font-parameter' frame property, as the frame
1672 parameter is not being changed by the user. */
1673 gui_set_frame_parameters_1 (f, arg, true);
1674 else
1675#endif
1676 Fmodify_frame_parameters (fr, arg);
1667 } 1677 }
1668 } 1678 }
1669 } 1679 }
diff --git a/src/frame.c b/src/frame.c
index f076a5ba54e..b57b296be54 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -4119,10 +4119,17 @@ frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
4119 If a parameter is not specially recognized, do nothing special; 4119 If a parameter is not specially recognized, do nothing special;
4120 otherwise call the `gui_set_...' function for that parameter. 4120 otherwise call the `gui_set_...' function for that parameter.
4121 Except for certain geometry properties, always call store_frame_param 4121 Except for certain geometry properties, always call store_frame_param
4122 to store the new value in the parameter alist. */ 4122 to store the new value in the parameter alist.
4123
4124 DEFAULT_PARAMETER should be set if the alist was not specified by
4125 the user, or by the face code to set the `font' parameter. In that
4126 case, the `font-parameter' frame parameter should not be changed,
4127 so dynamic-setting.el can restore the user's selected font
4128 correctly. */
4123 4129
4124void 4130void
4125gui_set_frame_parameters (struct frame *f, Lisp_Object alist) 4131gui_set_frame_parameters_1 (struct frame *f, Lisp_Object alist,
4132 bool default_parameter)
4126{ 4133{
4127 Lisp_Object tail, frame; 4134 Lisp_Object tail, frame;
4128 4135
@@ -4249,7 +4256,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
4249 } 4256 }
4250 else 4257 else
4251 { 4258 {
4252 register Lisp_Object param_index, old_value; 4259 Lisp_Object param_index, old_value;
4253 4260
4254 old_value = get_frame_param (f, prop); 4261 old_value = get_frame_param (f, prop);
4255 4262
@@ -4260,6 +4267,12 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
4260 && XFIXNAT (param_index) < ARRAYELTS (frame_parms) 4267 && XFIXNAT (param_index) < ARRAYELTS (frame_parms)
4261 && FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)]) 4268 && FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])
4262 (*(FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])) (f, val, old_value); 4269 (*(FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])) (f, val, old_value);
4270
4271 if (!default_parameter && EQ (prop, Qfont))
4272 /* The user manually specified the `font' frame parameter.
4273 Save that parameter for future use by the
4274 dynamic-setting code. */
4275 store_frame_param (f, Qfont_parameter, val);
4263 } 4276 }
4264 } 4277 }
4265 4278
@@ -4410,6 +4423,11 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
4410 SAFE_FREE (); 4423 SAFE_FREE ();
4411} 4424}
4412 4425
4426void
4427gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
4428{
4429 gui_set_frame_parameters_1 (f, alist, false);
4430}
4413 4431
4414/* Insert a description of internally-recorded parameters of frame F 4432/* Insert a description of internally-recorded parameters of frame F
4415 into the parameter alist *ALISTPTR that is to be given to the user. 4433 into the parameter alist *ALISTPTR that is to be given to the user.
@@ -4586,9 +4604,6 @@ gui_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4586{ 4604{
4587 Lisp_Object font_object; 4605 Lisp_Object font_object;
4588 int fontset = -1; 4606 int fontset = -1;
4589#ifdef HAVE_X_WINDOWS
4590 Lisp_Object font_param = arg;
4591#endif
4592 4607
4593 /* Set the frame parameter back to the old value because we may 4608 /* Set the frame parameter back to the old value because we may
4594 fail to use ARG as the new parameter value. */ 4609 fail to use ARG as the new parameter value. */
@@ -4627,16 +4642,10 @@ gui_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4627 error ("Unknown fontset: %s", SDATA (XCAR (arg))); 4642 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
4628 font_object = XCDR (arg); 4643 font_object = XCDR (arg);
4629 arg = AREF (font_object, FONT_NAME_INDEX); 4644 arg = AREF (font_object, FONT_NAME_INDEX);
4630#ifdef HAVE_X_WINDOWS
4631 font_param = Ffont_get (font_object, QCname);
4632#endif
4633 } 4645 }
4634 else if (FONT_OBJECT_P (arg)) 4646 else if (FONT_OBJECT_P (arg))
4635 { 4647 {
4636 font_object = arg; 4648 font_object = arg;
4637#ifdef HAVE_X_WINDOWS
4638 font_param = Ffont_get (font_object, QCname);
4639#endif
4640 /* This is to store the XLFD font name in the frame parameter for 4649 /* This is to store the XLFD font name in the frame parameter for
4641 backward compatibility. We should store the font-object 4650 backward compatibility. We should store the font-object
4642 itself in the future. */ 4651 itself in the future. */
@@ -4667,9 +4676,7 @@ gui_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4667 if (FRAME_TERMINAL (f)->set_new_font_hook) 4676 if (FRAME_TERMINAL (f)->set_new_font_hook)
4668 FRAME_TERMINAL (f)->set_new_font_hook (f, font_object, fontset); 4677 FRAME_TERMINAL (f)->set_new_font_hook (f, font_object, fontset);
4669 store_frame_param (f, Qfont, arg); 4678 store_frame_param (f, Qfont, arg);
4670#ifdef HAVE_X_WINDOWS 4679
4671 store_frame_param (f, Qfont_parameter, font_param);
4672#endif
4673 /* Recalculate tabbar height. */ 4680 /* Recalculate tabbar height. */
4674 f->n_tab_bar_rows = 0; 4681 f->n_tab_bar_rows = 0;
4675 /* Recalculate toolbar height. */ 4682 /* Recalculate toolbar height. */
@@ -4749,7 +4756,7 @@ gui_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_va
4749 if (FRAME_FONT (f)) 4756 if (FRAME_FONT (f))
4750 { 4757 {
4751 /* Reconsider default font after backend(s) change (Bug#23386). */ 4758 /* Reconsider default font after backend(s) change (Bug#23386). */
4752 FRAME_RIF(f)->default_font_parameter (f, Qnil); 4759 FRAME_RIF (f)->default_font_parameter (f, Qnil);
4753 face_change = true; 4760 face_change = true;
4754 windows_or_buffers_changed = 18; 4761 windows_or_buffers_changed = 18;
4755 } 4762 }
@@ -5451,12 +5458,20 @@ gui_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
5451 enum resource_types type) 5458 enum resource_types type)
5452{ 5459{
5453 Lisp_Object tem; 5460 Lisp_Object tem;
5461 bool was_unbound;
5454 5462
5455 tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type); 5463 tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type);
5464
5456 if (BASE_EQ (tem, Qunbound)) 5465 if (BASE_EQ (tem, Qunbound))
5457 tem = deflt; 5466 {
5467 tem = deflt;
5468 was_unbound = true;
5469 }
5470 else
5471 was_unbound = false;
5472
5458 AUTO_FRAME_ARG (arg, prop, tem); 5473 AUTO_FRAME_ARG (arg, prop, tem);
5459 gui_set_frame_parameters (f, arg); 5474 gui_set_frame_parameters_1 (f, arg, was_unbound);
5460 return tem; 5475 return tem;
5461} 5476}
5462 5477
@@ -5946,6 +5961,67 @@ This function is for internal use only. */)
5946 5961
5947 return f->was_invisible ? Qt : Qnil; 5962 return f->was_invisible ? Qt : Qnil;
5948} 5963}
5964
5965#ifdef HAVE_WINDOW_SYSTEM
5966
5967DEFUN ("reconsider-frame-fonts", Freconsider_frame_fonts,
5968 Sreconsider_frame_fonts, 1, 1, 0,
5969 doc: /* Recreate FRAME's default font using updated font parameters.
5970Signal an error if FRAME is not a window system frame. This should be
5971called after a `config-changed' event is received, signaling that the
5972parameters (such as pixel density) used by the system to open fonts
5973have changed. */)
5974 (Lisp_Object frame)
5975{
5976 struct frame *f;
5977 Lisp_Object params, font_parameter;
5978
5979 f = decode_window_system_frame (frame);
5980
5981 /* Kludge: if a `font' parameter was already specified,
5982 create an alist containing just that parameter. (bug#59371)
5983
5984 This sounds so simple, right? Well, read on below: */
5985 params = Qnil;
5986
5987 /* The difference between Qfont and Qfont_parameter is that the
5988 latter is not set automatically by the likes of x_new_font, and
5989 implicitly as the default face is realized. It is only set when
5990 the user specifically specifies a `font' frame parameter, and is
5991 cleared the moment the frame's font becomes defined by a face
5992 attribute, instead of through the `font' frame parameter. */
5993 font_parameter = get_frame_param (f, Qfont_parameter);
5994
5995 if (!NILP (font_parameter))
5996 params = list1 (Fcons (Qfont, font_parameter));
5997
5998 /* First, call this to reinitialize any font backend specific
5999 stuff. */
6000
6001 if (FRAME_RIF (f)->default_font_parameter)
6002 FRAME_RIF (f)->default_font_parameter (f, params);
6003
6004 /* For a mysterious reason, x_default_font_parameter sets Qfont to
6005 nil in the alist! */
6006
6007 if (!NILP (font_parameter))
6008 params = list1 (Fcons (Qfont, font_parameter));
6009
6010 /* Now call this to apply the existing value(s) of the `default'
6011 face. */
6012 call2 (Qface_set_after_frame_default, frame, params);
6013
6014 /* Restore the value of the `font-parameter' parameter, as
6015 `face-set-after-frame-default' will have changed it through its
6016 calls to `set-face-attribute'. */
6017 if (!NILP (font_parameter))
6018 store_frame_param (f, Qfont_parameter, font_parameter);
6019
6020 return Qnil;
6021}
6022
6023#endif
6024
5949 6025
5950/*********************************************************************** 6026/***********************************************************************
5951 Multimonitor data 6027 Multimonitor data
@@ -6201,6 +6277,7 @@ syms_of_frame (void)
6201 DEFSYM (Qiconify_top_level, "iconify-top-level"); 6277 DEFSYM (Qiconify_top_level, "iconify-top-level");
6202 DEFSYM (Qmake_invisible, "make-invisible"); 6278 DEFSYM (Qmake_invisible, "make-invisible");
6203 DEFSYM (Quse_frame_synchronization, "use-frame-synchronization"); 6279 DEFSYM (Quse_frame_synchronization, "use-frame-synchronization");
6280 DEFSYM (Qfont_parameter, "font-parameter");
6204 6281
6205 { 6282 {
6206 int i; 6283 int i;
@@ -6634,6 +6711,6 @@ iconify the top level frame instead. */);
6634#ifdef HAVE_WINDOW_SYSTEM 6711#ifdef HAVE_WINDOW_SYSTEM
6635 defsubr (&Sx_get_resource); 6712 defsubr (&Sx_get_resource);
6636 defsubr (&Sx_parse_geometry); 6713 defsubr (&Sx_parse_geometry);
6714 defsubr (&Sreconsider_frame_fonts);
6637#endif 6715#endif
6638
6639} 6716}
diff --git a/src/frame.h b/src/frame.h
index 458b6257e49..d6fd62b2ac2 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1670,6 +1670,7 @@ IMAGE_OPT_FROM_ID (struct frame *f, int id)
1670/* The class of this X application. */ 1670/* The class of this X application. */
1671#define EMACS_CLASS "Emacs" 1671#define EMACS_CLASS "Emacs"
1672 1672
1673extern void gui_set_frame_parameters_1 (struct frame *, Lisp_Object, bool);
1673extern void gui_set_frame_parameters (struct frame *, Lisp_Object); 1674extern void gui_set_frame_parameters (struct frame *, Lisp_Object);
1674extern void gui_set_fullscreen (struct frame *, Lisp_Object, Lisp_Object); 1675extern void gui_set_fullscreen (struct frame *, Lisp_Object, Lisp_Object);
1675extern void gui_set_line_spacing (struct frame *, Lisp_Object, Lisp_Object); 1676extern void gui_set_line_spacing (struct frame *, Lisp_Object, Lisp_Object);
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index dc765e5aee4..ede8f1323cd 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -737,7 +737,7 @@ struct font_driver const ftcrfont_driver =
737 .filter_properties = ftfont_filter_properties, 737 .filter_properties = ftfont_filter_properties,
738 .combining_capability = ftfont_combining_capability, 738 .combining_capability = ftfont_combining_capability,
739#ifdef HAVE_PGTK 739#ifdef HAVE_PGTK
740 .cached_font_ok = ftcrfont_cached_font_ok 740 .cached_font_ok = ftcrfont_cached_font_ok,
741#endif 741#endif
742 }; 742 };
743#ifdef HAVE_HARFBUZZ 743#ifdef HAVE_HARFBUZZ
@@ -755,6 +755,42 @@ syms_of_ftcrfont (void)
755 pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper); 755 pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper);
756} 756}
757 757
758#ifdef HAVE_X_WINDOWS
759
760/* Place the default font options used by Cairo on the given display
761 in OPTIONS. */
762
763void
764ftcrfont_get_default_font_options (struct x_display_info *dpyinfo,
765 cairo_font_options_t *options)
766{
767 Pixmap drawable;
768 cairo_surface_t *surface;
769
770 /* Cairo doesn't allow fetching the default font options for a
771 display, so the only option is to create a drawable, and an Xlib
772 surface for that drawable, and to get the font options from there
773 instead. */
774
775 drawable = XCreatePixmap (dpyinfo->display, dpyinfo->root_window,
776 1, 1, dpyinfo->n_planes);
777 surface = cairo_xlib_surface_create (dpyinfo->display, drawable,
778 dpyinfo->visual, 1, 1);
779
780 if (!surface)
781 {
782 XFreePixmap (dpyinfo->display, drawable);
783 return;
784 }
785
786 cairo_surface_get_font_options (surface, options);
787 XFreePixmap (dpyinfo->display, drawable);
788 cairo_surface_destroy (surface);
789 return;
790}
791
792#endif
793
758static void 794static void
759syms_of_ftcrfont_for_pdumper (void) 795syms_of_ftcrfont_for_pdumper (void)
760{ 796{
diff --git a/src/ftfont.h b/src/ftfont.h
index cfab8d3154f..ee56e2d7608 100644
--- a/src/ftfont.h
+++ b/src/ftfont.h
@@ -84,4 +84,11 @@ struct font_info
84#endif 84#endif
85}; 85};
86 86
87#if defined USE_CAIRO && defined HAVE_X_WINDOWS
88
89extern void ftcrfont_get_default_font_options (struct x_display_info *,
90 cairo_font_options_t *);
91
92#endif /* USE_CAIRO && HAVE_X_WINDOWS */
93
87#endif /* EMACS_FTFONT_H */ 94#endif /* EMACS_FTFONT_H */
diff --git a/src/gnutls.c b/src/gnutls.c
index a0de0238c47..7f0aaf85a41 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -2790,6 +2790,10 @@ Any GnuTLS extension with ID up to 100
2790 2790
2791 capabilities = Fcons (intern("gnutls"), capabilities); 2791 capabilities = Fcons (intern("gnutls"), capabilities);
2792 2792
2793# ifdef HAVE_GNUTLS_EXT__DUMBFW
2794 capabilities = Fcons (intern("ClientHello Padding"), capabilities);
2795# endif
2796
2793# ifdef HAVE_GNUTLS3 2797# ifdef HAVE_GNUTLS3
2794 capabilities = Fcons (intern("gnutls3"), capabilities); 2798 capabilities = Fcons (intern("gnutls3"), capabilities);
2795 capabilities = Fcons (intern("digests"), capabilities); 2799 capabilities = Fcons (intern("digests"), capabilities);
@@ -2807,16 +2811,14 @@ Any GnuTLS extension with ID up to 100
2807 const char* name = gnutls_ext_get_name(ext); 2811 const char* name = gnutls_ext_get_name(ext);
2808 if (name != NULL) 2812 if (name != NULL)
2809 { 2813 {
2810 capabilities = Fcons (intern(name), capabilities); 2814 Lisp_Object cap = intern (name);
2815 if (NILP (Fmemq (cap, capabilities)))
2816 capabilities = Fcons (cap, capabilities);
2811 } 2817 }
2812 } 2818 }
2813# endif 2819# endif
2814# endif /* HAVE_GNUTLS3 */ 2820# endif /* HAVE_GNUTLS3 */
2815 2821
2816# ifdef HAVE_GNUTLS_EXT__DUMBFW
2817 capabilities = Fcons (intern("ClientHello Padding"), capabilities);
2818# endif
2819
2820# ifdef WINDOWSNT 2822# ifdef WINDOWSNT
2821 Vlibrary_cache = Fcons (Fcons (Qgnutls, capabilities), Vlibrary_cache); 2823 Vlibrary_cache = Fcons (Fcons (Qgnutls, capabilities), Vlibrary_cache);
2822# endif /* WINDOWSNT */ 2824# endif /* WINDOWSNT */
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index 0f8e26d0db4..3a982856777 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -653,6 +653,24 @@ public:
653 Quit (); 653 Quit ();
654 else if (msg->what == B_CLIPBOARD_CHANGED) 654 else if (msg->what == B_CLIPBOARD_CHANGED)
655 haiku_write (CLIPBOARD_CHANGED_EVENT, &rq); 655 haiku_write (CLIPBOARD_CHANGED_EVENT, &rq);
656 else if (msg->what == B_KEY_MAP_LOADED)
657 {
658 /* Install the new keymap. Or rather, clear key_map -- Emacs
659 will fetch it again from the main thread the next time it
660 is needed. */
661 if (key_map_lock.Lock ())
662 {
663 if (key_map)
664 free (key_map);
665
666 if (key_chars)
667 free (key_chars);
668
669 key_map = NULL;
670 key_chars = NULL;
671 key_map_lock.Unlock ();
672 }
673 }
656 else 674 else
657 BApplication::MessageReceived (msg); 675 BApplication::MessageReceived (msg);
658 } 676 }
diff --git a/src/haiku_support.h b/src/haiku_support.h
index e940e69bf11..2605a75b400 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -383,7 +383,7 @@ struct haiku_font_pattern
383 /* The number of characters in `wanted_chars'. */ 383 /* The number of characters in `wanted_chars'. */
384 int want_chars_len; 384 int want_chars_len;
385 385
386 /* List of characters. The font must fullfill at least one of 386 /* List of characters. The font must fulfill at least one of
387 them for the match to succeed. */ 387 them for the match to succeed. */
388 int *need_one_of; 388 int *need_one_of;
389 389
diff --git a/src/haikufns.c b/src/haikufns.c
index 711202c5df3..5717d0354f8 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -175,10 +175,19 @@ haiku_change_tool_bar_height (struct frame *f, int height)
175void 175void
176haiku_change_tab_bar_height (struct frame *f, int height) 176haiku_change_tab_bar_height (struct frame *f, int height)
177{ 177{
178 int unit = FRAME_LINE_HEIGHT (f); 178 int unit, old_height, lines;
179 int old_height = FRAME_TAB_BAR_HEIGHT (f); 179 Lisp_Object fullscreen;
180 int lines = (height + unit - 1) / unit; 180
181 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); 181 unit = FRAME_LINE_HEIGHT (f);
182 old_height = FRAME_TAB_BAR_HEIGHT (f);
183 fullscreen = get_frame_param (f, Qfullscreen);
184
185 /* This differs from the tool bar code in that the tab bar height is
186 not rounded up. Otherwise, if redisplay_tab_bar decides to grow
187 the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
188 leading to the tab bar height being incorrectly set upon the next
189 call to x_set_font. (bug#59285) */
190 lines = height / unit;
182 191
183 /* Make sure we redisplay all windows in this frame. */ 192 /* Make sure we redisplay all windows in this frame. */
184 fset_redisplay (f); 193 fset_redisplay (f);
diff --git a/src/haikuselect.c b/src/haikuselect.c
index bd004f4900a..e8d3b5f0f7f 100644
--- a/src/haikuselect.c
+++ b/src/haikuselect.c
@@ -1260,7 +1260,7 @@ syms_of_haikuselect (void)
1260{ 1260{
1261 DEFVAR_BOOL ("haiku-signal-invalid-refs", haiku_signal_invalid_refs, 1261 DEFVAR_BOOL ("haiku-signal-invalid-refs", haiku_signal_invalid_refs,
1262 doc: /* If nil, silently ignore invalid file names in system messages. 1262 doc: /* If nil, silently ignore invalid file names in system messages.
1263Otherwise, an error will be signalled if adding a file reference to a 1263Otherwise, an error will be signaled if adding a file reference to a
1264system message failed. */); 1264system message failed. */);
1265 haiku_signal_invalid_refs = true; 1265 haiku_signal_invalid_refs = true;
1266 1266
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 4e32b747160..496480cbc09 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -3007,9 +3007,11 @@ haiku_default_font_parameter (struct frame *f, Lisp_Object parms)
3007 font = font_open_by_spec (f, Ffont_get_system_font ()); 3007 font = font_open_by_spec (f, Ffont_get_system_font ());
3008 3008
3009 if (NILP (font)) 3009 if (NILP (font))
3010 font = !NILP (font_param) ? font_param 3010 font = (!NILP (font_param)
3011 : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", 3011 ? font_param
3012 RES_TYPE_STRING); 3012 : gui_display_get_arg (dpyinfo, parms, Qfont,
3013 "font", "Font",
3014 RES_TYPE_STRING));
3013 3015
3014 if (! FONTP (font) && ! STRINGP (font)) 3016 if (! FONTP (font) && ! STRINGP (font))
3015 { 3017 {
@@ -3029,13 +3031,6 @@ haiku_default_font_parameter (struct frame *f, Lisp_Object parms)
3029 if (NILP (font)) 3031 if (NILP (font))
3030 error ("No suitable font was found"); 3032 error ("No suitable font was found");
3031 } 3033 }
3032 else if (!NILP (font_param))
3033 {
3034 /* Remember the explicit font parameter, so we can re-apply it
3035 after we've applied the `default' face settings. */
3036 AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
3037 gui_set_frame_parameters (f, arg);
3038 }
3039 3034
3040 gui_default_parameter (f, parms, Qfont, font, "font", "Font", 3035 gui_default_parameter (f, parms, Qfont, font, "font", "Font",
3041 RES_TYPE_STRING); 3036 RES_TYPE_STRING);
diff --git a/src/image.c b/src/image.c
index 1e323ba66a0..600c32571e1 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1843,7 +1843,9 @@ image_clear_image (struct frame *f, struct image *img)
1843{ 1843{
1844 block_input (); 1844 block_input ();
1845 image_clear_image_1 (f, img, 1845 image_clear_image_1 (f, img,
1846 CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS); 1846 (CLEAR_IMAGE_PIXMAP
1847 | CLEAR_IMAGE_MASK
1848 | CLEAR_IMAGE_COLORS));
1847 unblock_input (); 1849 unblock_input ();
1848} 1850}
1849 1851
@@ -2980,7 +2982,8 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id)
2980 unblock_input (); 2982 unblock_input ();
2981 } 2983 }
2982 2984
2983 /* We're using IMG, so set its timestamp to `now'. */ 2985 /* IMG is now being used, so set its timestamp to the current
2986 time. */
2984 img->timestamp = current_timespec (); 2987 img->timestamp = current_timespec ();
2985 2988
2986 /* Value is the image id. */ 2989 /* Value is the image id. */
@@ -3238,12 +3241,13 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
3238static void 3241static void
3239x_destroy_x_image (XImage *ximg) 3242x_destroy_x_image (XImage *ximg)
3240{ 3243{
3241 eassert (input_blocked_p ());
3242 if (ximg) 3244 if (ximg)
3243 { 3245 {
3244 xfree (ximg->data); 3246 xfree (ximg->data);
3245 ximg->data = NULL; 3247 ximg->data = NULL;
3246 } 3248 }
3249
3250 XDestroyImage (ximg);
3247} 3251}
3248 3252
3249# if !defined USE_CAIRO && defined HAVE_XRENDER 3253# if !defined USE_CAIRO && defined HAVE_XRENDER
@@ -6224,26 +6228,28 @@ static void
6224image_from_emacs_colors (struct frame *f, struct image *img, Emacs_Color *colors) 6228image_from_emacs_colors (struct frame *f, struct image *img, Emacs_Color *colors)
6225{ 6229{
6226 int x, y; 6230 int x, y;
6227 Emacs_Pix_Container oimg = NULL; 6231 Emacs_Pix_Container ximage;
6228 Emacs_Color *p; 6232 Emacs_Color *p;
6229 6233
6234 ximage = NULL;
6235
6230 init_color_table (); 6236 init_color_table ();
6231 6237
6232 image_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_COLORS); 6238 image_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_COLORS);
6233 image_create_x_image_and_pixmap (f, img, img->width, img->height, 0, 6239 image_create_x_image_and_pixmap (f, img, img->width, img->height, 0,
6234 &oimg, 0); 6240 &ximage, 0);
6235 p = colors; 6241 p = colors;
6236 for (y = 0; y < img->height; ++y) 6242 for (y = 0; y < img->height; ++y)
6237 for (x = 0; x < img->width; ++x, ++p) 6243 for (x = 0; x < img->width; ++x, ++p)
6238 { 6244 {
6239 unsigned long pixel; 6245 unsigned long pixel;
6240 pixel = lookup_rgb_color (f, p->red, p->green, p->blue); 6246 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
6241 PUT_PIXEL (oimg, x, y, pixel); 6247 PUT_PIXEL (ximage, x, y, pixel);
6242 } 6248 }
6243 6249
6244 xfree (colors); 6250 xfree (colors);
6245 6251
6246 image_put_x_image (f, img, oimg, 0); 6252 image_put_x_image (f, img, ximage, false);
6247#ifdef COLOR_TABLE_SUPPORT 6253#ifdef COLOR_TABLE_SUPPORT
6248 img->colors = colors_in_color_table (&img->ncolors); 6254 img->colors = colors_in_color_table (&img->ncolors);
6249 free_color_table (); 6255 free_color_table ();
@@ -12207,7 +12213,15 @@ non-numeric, there is no explicit limit on the size of images. */);
12207# endif 12213# endif
12208 DEFSYM (Qgobject, "gobject"); 12214 DEFSYM (Qgobject, "gobject");
12209#endif /* HAVE_NTGUI */ 12215#endif /* HAVE_NTGUI */
12210#endif /* HAVE_RSVG */ 12216#elif defined HAVE_NATIVE_IMAGE_API \
12217 && ((defined HAVE_NS && defined NS_IMPL_COCOA) \
12218 || defined HAVE_HAIKU)
12219 DEFSYM (Qsvg, "svg");
12220
12221 /* On Haiku, the SVG translator may not be installed. */
12222 if (image_can_use_native_api (Qsvg))
12223 add_image_type (Qsvg);
12224#endif
12211 12225
12212#ifdef HAVE_NS 12226#ifdef HAVE_NS
12213 DEFSYM (Qheic, "heic"); 12227 DEFSYM (Qheic, "heic");
diff --git a/src/insdel.c b/src/insdel.c
index 6d56a76c77a..03ce59b3409 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -268,6 +268,7 @@ adjust_markers_for_delete (ptrdiff_t from, ptrdiff_t from_byte,
268 m->bytepos = from_byte; 268 m->bytepos = from_byte;
269 } 269 }
270 } 270 }
271 adjust_overlays_for_delete (from, to - from);
271} 272}
272 273
273 274
@@ -307,6 +308,7 @@ adjust_markers_for_insert (ptrdiff_t from, ptrdiff_t from_byte,
307 m->charpos += nchars; 308 m->charpos += nchars;
308 } 309 }
309 } 310 }
311 adjust_overlays_for_insert (from, to - from, before_markers);
310} 312}
311 313
312/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters. 314/* Adjust point for an insertion of NBYTES bytes, which are NCHARS characters.
@@ -343,6 +345,11 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
343 ptrdiff_t diff_bytes = new_bytes - old_bytes; 345 ptrdiff_t diff_bytes = new_bytes - old_bytes;
344 346
345 adjust_suspend_auto_hscroll (from, from + old_chars); 347 adjust_suspend_auto_hscroll (from, from + old_chars);
348
349 /* FIXME: When OLD_CHARS is 0, this "replacement" is really just an
350 insertion, but the behavior we provide here in that case is that of
351 `insert-before-markers` rather than that of `insert`.
352 Maybe not a bug, but not a feature either. */
346 for (m = BUF_MARKERS (current_buffer); m; m = m->next) 353 for (m = BUF_MARKERS (current_buffer); m; m = m->next)
347 { 354 {
348 if (m->bytepos >= prev_to_byte) 355 if (m->bytepos >= prev_to_byte)
@@ -358,6 +365,10 @@ adjust_markers_for_replace (ptrdiff_t from, ptrdiff_t from_byte,
358 } 365 }
359 366
360 check_markers (); 367 check_markers ();
368
369 adjust_overlays_for_insert (from + old_chars, new_chars, true);
370 if (old_chars)
371 adjust_overlays_for_delete (from, old_chars);
361} 372}
362 373
363/* Starting at POS (BYTEPOS), find the byte position corresponding to 374/* Starting at POS (BYTEPOS), find the byte position corresponding to
@@ -917,7 +928,6 @@ insert_1_both (const char *string,
917 if (Z - GPT < END_UNCHANGED) 928 if (Z - GPT < END_UNCHANGED)
918 END_UNCHANGED = Z - GPT; 929 END_UNCHANGED = Z - GPT;
919 930
920 adjust_overlays_for_insert (PT, nchars);
921 adjust_markers_for_insert (PT, PT_BYTE, 931 adjust_markers_for_insert (PT, PT_BYTE,
922 PT + nchars, PT_BYTE + nbytes, 932 PT + nchars, PT_BYTE + nbytes,
923 before_markers); 933 before_markers);
@@ -1043,7 +1053,6 @@ insert_from_string_1 (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1043 if (Z - GPT < END_UNCHANGED) 1053 if (Z - GPT < END_UNCHANGED)
1044 END_UNCHANGED = Z - GPT; 1054 END_UNCHANGED = Z - GPT;
1045 1055
1046 adjust_overlays_for_insert (PT, nchars);
1047 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, 1056 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1048 PT_BYTE + outgoing_nbytes, 1057 PT_BYTE + outgoing_nbytes,
1049 before_markers); 1058 before_markers);
@@ -1115,9 +1124,8 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1115 1124
1116 insert_from_gap_1 (nchars, nbytes, text_at_gap_tail); 1125 insert_from_gap_1 (nchars, nbytes, text_at_gap_tail);
1117 1126
1118 adjust_overlays_for_insert (ins_charpos, nchars);
1119 adjust_markers_for_insert (ins_charpos, ins_bytepos, 1127 adjust_markers_for_insert (ins_charpos, ins_bytepos,
1120 ins_charpos + nchars, ins_bytepos + nbytes, 0); 1128 ins_charpos + nchars, ins_bytepos + nbytes, false);
1121 1129
1122 if (buffer_intervals (current_buffer)) 1130 if (buffer_intervals (current_buffer))
1123 { 1131 {
@@ -1257,10 +1265,9 @@ insert_from_buffer_1 (struct buffer *buf,
1257 if (Z - GPT < END_UNCHANGED) 1265 if (Z - GPT < END_UNCHANGED)
1258 END_UNCHANGED = Z - GPT; 1266 END_UNCHANGED = Z - GPT;
1259 1267
1260 adjust_overlays_for_insert (PT, nchars);
1261 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, 1268 adjust_markers_for_insert (PT, PT_BYTE, PT + nchars,
1262 PT_BYTE + outgoing_nbytes, 1269 PT_BYTE + outgoing_nbytes,
1263 0); 1270 false);
1264 1271
1265 offset_intervals (current_buffer, PT, nchars); 1272 offset_intervals (current_buffer, PT, nchars);
1266 1273
@@ -1316,17 +1323,12 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
1316 len, len_byte); 1323 len, len_byte);
1317 else 1324 else
1318 adjust_markers_for_insert (from, from_byte, 1325 adjust_markers_for_insert (from, from_byte,
1319 from + len, from_byte + len_byte, 0); 1326 from + len, from_byte + len_byte, false);
1320 1327
1321 if (nchars_del > 0) 1328 if (nchars_del > 0)
1322 record_delete (from, prev_text, false); 1329 record_delete (from, prev_text, false);
1323 record_insert (from, len); 1330 record_insert (from, len);
1324 1331
1325 if (len > nchars_del)
1326 adjust_overlays_for_insert (from, len - nchars_del);
1327 else if (len < nchars_del)
1328 adjust_overlays_for_delete (from, nchars_del - len);
1329
1330 offset_intervals (current_buffer, from, len - nchars_del); 1332 offset_intervals (current_buffer, from, len - nchars_del);
1331 1333
1332 if (from < PT) 1334 if (from < PT)
@@ -1338,8 +1340,6 @@ adjust_after_replace (ptrdiff_t from, ptrdiff_t from_byte,
1338 1340
1339 check_markers (); 1341 check_markers ();
1340 1342
1341 if (len == 0)
1342 evaporate_overlays (from);
1343 modiff_incr (&MODIFF, nchars_del + len); 1343 modiff_incr (&MODIFF, nchars_del + len);
1344 CHARS_MODIFF = MODIFF; 1344 CHARS_MODIFF = MODIFF;
1345} 1345}
@@ -1507,14 +1507,9 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
1507 which make the original byte positions of the markers 1507 which make the original byte positions of the markers
1508 invalid. */ 1508 invalid. */
1509 adjust_markers_bytepos (from, from_byte, from + inschars, 1509 adjust_markers_bytepos (from, from_byte, from + inschars,
1510 from_byte + outgoing_insbytes, 1); 1510 from_byte + outgoing_insbytes, true);
1511 } 1511 }
1512 1512
1513 /* Adjust the overlay center as needed. This must be done after
1514 adjusting the markers that bound the overlays. */
1515 adjust_overlays_for_delete (from, nchars_del);
1516 adjust_overlays_for_insert (from, inschars);
1517
1518 offset_intervals (current_buffer, from, inschars - nchars_del); 1513 offset_intervals (current_buffer, from, inschars - nchars_del);
1519 1514
1520 /* Get the intervals for the part of the string we are inserting-- 1515 /* Get the intervals for the part of the string we are inserting--
@@ -1530,9 +1525,6 @@ replace_range (ptrdiff_t from, ptrdiff_t to, Lisp_Object new,
1530 (from_byte + outgoing_insbytes 1525 (from_byte + outgoing_insbytes
1531 - (PT_BYTE < to_byte ? PT_BYTE : to_byte))); 1526 - (PT_BYTE < to_byte ? PT_BYTE : to_byte)));
1532 1527
1533 if (outgoing_insbytes == 0)
1534 evaporate_overlays (from);
1535
1536 check_markers (); 1528 check_markers ();
1537 1529
1538 modiff_incr (&MODIFF, nchars_del + inschars); 1530 modiff_incr (&MODIFF, nchars_del + inschars);
@@ -1640,18 +1632,10 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1640 sequences which make the original byte positions of the 1632 sequences which make the original byte positions of the
1641 markers invalid. */ 1633 markers invalid. */
1642 adjust_markers_bytepos (from, from_byte, from + inschars, 1634 adjust_markers_bytepos (from, from_byte, from + inschars,
1643 from_byte + insbytes, 1); 1635 from_byte + insbytes, true);
1644 } 1636 }
1645 } 1637 }
1646 1638
1647 /* Adjust the overlay center as needed. This must be done after
1648 adjusting the markers that bound the overlays. */
1649 if (nchars_del != inschars)
1650 {
1651 adjust_overlays_for_insert (from, inschars);
1652 adjust_overlays_for_delete (from + inschars, nchars_del);
1653 }
1654
1655 offset_intervals (current_buffer, from, inschars - nchars_del); 1639 offset_intervals (current_buffer, from, inschars - nchars_del);
1656 1640
1657 /* Relocate point as if it were a marker. */ 1641 /* Relocate point as if it were a marker. */
@@ -1664,9 +1648,6 @@ replace_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1664 adjust_point (inschars - nchars_del, insbytes - nbytes_del); 1648 adjust_point (inschars - nchars_del, insbytes - nbytes_del);
1665 } 1649 }
1666 1650
1667 if (insbytes == 0)
1668 evaporate_overlays (from);
1669
1670 check_markers (); 1651 check_markers ();
1671 1652
1672 modiff_incr (&MODIFF, nchars_del + inschars); 1653 modiff_incr (&MODIFF, nchars_del + inschars);
@@ -1854,10 +1835,6 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1854 1835
1855 offset_intervals (current_buffer, from, - nchars_del); 1836 offset_intervals (current_buffer, from, - nchars_del);
1856 1837
1857 /* Adjust the overlay center as needed. This must be done after
1858 adjusting the markers that bound the overlays. */
1859 adjust_overlays_for_delete (from, nchars_del);
1860
1861 GAP_SIZE += nbytes_del; 1838 GAP_SIZE += nbytes_del;
1862 ZV_BYTE -= nbytes_del; 1839 ZV_BYTE -= nbytes_del;
1863 Z_BYTE -= nbytes_del; 1840 Z_BYTE -= nbytes_del;
@@ -1879,8 +1856,6 @@ del_range_2 (ptrdiff_t from, ptrdiff_t from_byte,
1879 1856
1880 check_markers (); 1857 check_markers ();
1881 1858
1882 evaporate_overlays (from);
1883
1884 return deletion; 1859 return deletion;
1885} 1860}
1886 1861
diff --git a/src/itree.c b/src/itree.c
index 3b10802ff09..04fa9e827a2 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -70,7 +70,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
70 but not the END. The previous/next overlay change operations need 70 but not the END. The previous/next overlay change operations need
71 to find the nearest point where there is *either* an interval BEG 71 to find the nearest point where there is *either* an interval BEG
72 or END point, but there is no efficient way to narrow the search 72 or END point, but there is no efficient way to narrow the search
73 space over END postions. 73 space over END positions.
74 74
75 Consider the case where next-overlay-change is called at POS, all 75 Consider the case where next-overlay-change is called at POS, all
76 interval BEG positions are less than pos POS and all interval END 76 interval BEG positions are less than pos POS and all interval END
@@ -111,7 +111,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
111 In order to avoid this, we introduce yet another node attribute, 111 In order to avoid this, we introduce yet another node attribute,
112 called OFFSET. 112 called OFFSET.
113 113
114 The OFFSET of some some subtree, represented by its root, is the 114 The OFFSET of some subtree, represented by its root, is the
115 amount of shift that needs to be applied to its BEGIN, END and 115 amount of shift that needs to be applied to its BEGIN, END and
116 LIMIT values, in order to get to the actual buffer positions. 116 LIMIT values, in order to get to the actual buffer positions.
117 Coming back to the example, all we would need to do in this case, 117 Coming back to the example, all we would need to do in this case,
@@ -131,43 +131,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
131 * | Stack 131 * | Stack
132 * +=======================================================================+ */ 132 * +=======================================================================+ */
133 133
134typedef uintptr_t nodeptr_and_flag;
135
136static inline nodeptr_and_flag
137make_nav (struct itree_node *ptr, bool flag)
138{
139 uintptr_t v = (uintptr_t) ptr;
140 /* We assume alignment imposes the LSB is clear for us to use it. */
141 eassert (!(v & 1));
142 return v | !!flag;
143}
144
145static inline struct itree_node *
146nav_nodeptr (nodeptr_and_flag nav)
147{
148 return (struct itree_node *) (nav & (~(uintptr_t)1));
149}
150
151static inline bool
152nav_flag (nodeptr_and_flag nav)
153{
154 return (bool) (nav & 1);
155}
156
157/* Simple dynamic array. */ 134/* Simple dynamic array. */
158struct interval_stack 135struct itree_stack
159{ 136{
160 nodeptr_and_flag *nodes; 137 struct itree_node **nodes;
161 size_t size; 138 size_t size;
162 size_t length; 139 size_t length;
163}; 140};
164 141
165/* This is just a simple dynamic array with stack semantics. */ 142/* This is just a simple dynamic array with stack semantics. */
166 143
167static struct interval_stack* 144static struct itree_stack*
168interval_stack_create (intmax_t initial_size) 145itree_stack_create (intmax_t initial_size)
169{ 146{
170 struct interval_stack *stack = xmalloc (sizeof (struct interval_stack)); 147 struct itree_stack *stack = xmalloc (sizeof (struct itree_stack));
171 stack->size = max (0, initial_size); 148 stack->size = max (0, initial_size);
172 stack->nodes = xmalloc (stack->size * sizeof (struct itree_node*)); 149 stack->nodes = xmalloc (stack->size * sizeof (struct itree_node*));
173 stack->length = 0; 150 stack->length = 0;
@@ -175,7 +152,7 @@ interval_stack_create (intmax_t initial_size)
175} 152}
176 153
177static void 154static void
178interval_stack_destroy (struct interval_stack *stack) 155itree_stack_destroy (struct itree_stack *stack)
179{ 156{
180 if (! stack) 157 if (! stack)
181 return; 158 return;
@@ -184,14 +161,8 @@ interval_stack_destroy (struct interval_stack *stack)
184 xfree (stack); 161 xfree (stack);
185} 162}
186 163
187static void
188interval_stack_clear (struct interval_stack *stack)
189{
190 stack->length = 0;
191}
192
193static inline void 164static inline void
194interval_stack_ensure_space (struct interval_stack *stack, intmax_t nelements) 165itree_stack_ensure_space (struct itree_stack *stack, uintmax_t nelements)
195{ 166{
196 if (nelements > stack->size) 167 if (nelements > stack->size)
197 { 168 {
@@ -204,95 +175,32 @@ interval_stack_ensure_space (struct interval_stack *stack, intmax_t nelements)
204/* Push NODE on the STACK, while settings its visited flag to FLAG. */ 175/* Push NODE on the STACK, while settings its visited flag to FLAG. */
205 176
206static inline void 177static inline void
207interval_stack_push_flagged (struct interval_stack *stack, 178itree_stack_push (struct itree_stack *stack, struct itree_node *node)
208 struct itree_node *node, bool flag)
209{ 179{
210 eassert (node && node != NULL); 180 eassert (node);
211 181 itree_stack_ensure_space (stack, stack->length + 1);
212 /* FIXME: While the stack used in the iterator is bounded by the tree
213 depth and could be easily pre-allocated to a large enough size to avoid
214 this "ensure" check, `interval_stack_push` is also used elsewhere to
215 simply collect some subset of the overlays, where it's only bounded by
216 the total number of overlays in the buffer (which can be large and thus
217 preferably not pre-allocated needlessly). */
218 interval_stack_ensure_space (stack, stack->length + 1);
219 182
220 stack->nodes[stack->length] = make_nav (node, flag); 183 stack->nodes[stack->length] = node;
221 stack->length++; 184 stack->length++;
222} 185}
223 186
224static inline void 187static inline struct itree_node *
225interval_stack_push (struct interval_stack *stack, struct itree_node *node) 188itree_stack_pop (struct itree_stack *stack)
226{
227 interval_stack_push_flagged (stack, node, false);
228}
229
230static inline nodeptr_and_flag
231interval_stack_pop (struct interval_stack *stack)
232{ 189{
233 if (stack->length == 0) 190 if (stack->length == 0)
234 return make_nav (NULL, false); 191 return NULL;
235 return stack->nodes[--stack->length]; 192 return stack->nodes[--stack->length];
236} 193}
237 194
238 195
239/* +-----------------------------------------------------------------------+ */ 196/* +-----------------------------------------------------------------------+ */
240 197
241/* State used when iterating interval. */
242struct itree_iterator
243{
244 struct interval_stack *stack;
245 ptrdiff_t begin;
246 ptrdiff_t end;
247
248 /* A copy of the tree's `otick`. */
249 uintmax_t otick;
250 enum itree_order order;
251 bool running;
252 const char *file;
253 int line;
254};
255
256/* Ideally, every iteration would use its own `iter` object, so we could
257 have several iterations active at the same time. In practice, iterations
258 are limited by the fact we don't allow modifying the tree at the same
259 time, making the use of nested iterations quite rare anyway.
260 So we just use a single global iterator instead for now. */
261static struct itree_iterator *iter;
262
263static int 198static int
264interval_tree_max_height (const struct itree_tree *tree) 199itree_max_height (const struct itree_tree *tree)
265{ 200{
266 return 2 * log (tree->size + 1) / log (2) + 0.5; 201 return 2 * log (tree->size + 1) / log (2) + 0.5;
267} 202}
268 203
269/* Allocate a new iterator for TREE. */
270
271static struct itree_iterator *
272itree_iterator_create (struct itree_tree *tree)
273{
274 struct itree_iterator *g = xmalloc (sizeof *g);
275 /* 19 here just avoids starting with a silly-small stack.
276 FIXME: Since this stack only needs to be about 2*max_depth
277 in the worst case, we could completely pre-allocate it to something
278 like word-bit-size * 2 and then never worry about growing it. */
279 const int size = (tree ? interval_tree_max_height (tree) : 19) + 1;
280
281 g->stack = interval_stack_create (size);
282 g->running = false;
283 g->begin = 0;
284 g->end = 0;
285 g->file = NULL;
286 g->line = 0;
287 return g;
288}
289
290static void
291itree_init (void)
292{
293 iter = itree_iterator_create (NULL);
294}
295
296struct check_subtree_result 204struct check_subtree_result
297{ 205{
298 /* Node count of the tree. */ 206 /* Node count of the tree. */
@@ -325,7 +233,7 @@ check_subtree (struct itree_node *node,
325 and <= to its parent's otick. 233 and <= to its parent's otick.
326 234
327 Note: we cannot assert that (NODE.otick == NODE.parent.otick) 235 Note: we cannot assert that (NODE.otick == NODE.parent.otick)
328 implies (NODE.offset == 0) because interval_tree_inherit_offset() 236 implies (NODE.offset == 0) because itree_inherit_offset()
329 doesn't always update otick. It could, but it is not clear there 237 doesn't always update otick. It could, but it is not clear there
330 is a need. */ 238 is a need. */
331 eassert (node->otick <= tree_otick); 239 eassert (node->otick <= tree_otick);
@@ -429,7 +337,7 @@ itree_newlimit (struct itree_node *node)
429/* Update NODE's limit attribute according to its children. */ 337/* Update NODE's limit attribute according to its children. */
430 338
431static void 339static void
432interval_tree_update_limit (struct itree_node *node) 340itree_update_limit (struct itree_node *node)
433{ 341{
434 if (node == NULL) 342 if (node == NULL)
435 return; 343 return;
@@ -444,7 +352,7 @@ interval_tree_update_limit (struct itree_node *node)
444*/ 352*/
445 353
446static void 354static void
447interval_tree_inherit_offset (uintmax_t otick, struct itree_node *node) 355itree_inherit_offset (uintmax_t otick, struct itree_node *node)
448{ 356{
449 eassert (node->parent == NULL || node->parent->otick >= node->otick); 357 eassert (node->parent == NULL || node->parent->otick >= node->otick);
450 if (node->otick == otick) 358 if (node->otick == otick)
@@ -481,7 +389,7 @@ interval_tree_inherit_offset (uintmax_t otick, struct itree_node *node)
481 stable, i.e. new_limit = old_limit. */ 389 stable, i.e. new_limit = old_limit. */
482 390
483static void 391static void
484interval_tree_propagate_limit (struct itree_node *node) 392itree_propagate_limit (struct itree_node *node)
485{ 393{
486 ptrdiff_t newlimit; 394 ptrdiff_t newlimit;
487 395
@@ -502,15 +410,15 @@ interval_tree_propagate_limit (struct itree_node *node)
502} 410}
503 411
504static struct itree_node* 412static struct itree_node*
505interval_tree_validate (struct itree_tree *tree, struct itree_node *node) 413itree_validate (struct itree_tree *tree, struct itree_node *node)
506{ 414{
507 415
508 if (tree->otick == node->otick || node == NULL) 416 if (tree->otick == node->otick || node == NULL)
509 return node; 417 return node;
510 if (node != tree->root) 418 if (node != tree->root)
511 interval_tree_validate (tree, node->parent); 419 itree_validate (tree, node->parent);
512 420
513 interval_tree_inherit_offset (tree->otick, node); 421 itree_inherit_offset (tree->otick, node);
514 return node; 422 return node;
515} 423}
516 424
@@ -541,7 +449,7 @@ ptrdiff_t
541itree_node_begin (struct itree_tree *tree, 449itree_node_begin (struct itree_tree *tree,
542 struct itree_node *node) 450 struct itree_node *node)
543{ 451{
544 interval_tree_validate (tree, node); 452 itree_validate (tree, node);
545 return node->begin; 453 return node->begin;
546} 454}
547 455
@@ -551,20 +459,15 @@ ptrdiff_t
551itree_node_end (struct itree_tree *tree, 459itree_node_end (struct itree_tree *tree,
552 struct itree_node *node) 460 struct itree_node *node)
553{ 461{
554 interval_tree_validate (tree, node); 462 itree_validate (tree, node);
555 return node->end; 463 return node->end;
556} 464}
557 465
558/* Allocate an interval_tree. Free with interval_tree_destroy. */ 466/* Allocate an itree_tree. Free with itree_destroy. */
559 467
560struct itree_tree * 468struct itree_tree *
561itree_create (void) 469itree_create (void)
562{ 470{
563 /* FIXME? Maybe avoid the initialization of itree_null in the same
564 way that is used to call mem_init in alloc.c? It's not really
565 important though. */
566 itree_init ();
567
568 struct itree_tree *tree = xmalloc (sizeof (*tree)); 471 struct itree_tree *tree = xmalloc (sizeof (*tree));
569 itree_clear (tree); 472 itree_clear (tree);
570 return tree; 473 return tree;
@@ -584,10 +487,9 @@ itree_clear (struct itree_tree *tree)
584/* Initialize a pre-allocated tree (presumably on the stack). */ 487/* Initialize a pre-allocated tree (presumably on the stack). */
585 488
586static void 489static void
587interval_tree_init (struct interval_tree *tree) 490itree_init (struct itree_tree *tree)
588{ 491{
589 interval_tree_clear (tree); 492 itree_clear (tree);
590 /* tree->iter = itree_iterator_create (tree); */
591} 493}
592#endif 494#endif
593 495
@@ -596,8 +498,6 @@ void
596itree_destroy (struct itree_tree *tree) 498itree_destroy (struct itree_tree *tree)
597{ 499{
598 eassert (tree->root == NULL); 500 eassert (tree->root == NULL);
599 /* if (tree->iter)
600 * itree_iterator_destroy (tree->iter); */
601 xfree (tree); 501 xfree (tree);
602} 502}
603 503
@@ -612,15 +512,15 @@ itree_size (struct itree_tree *tree)
612/* Perform the familiar left-rotation on node NODE. */ 512/* Perform the familiar left-rotation on node NODE. */
613 513
614static void 514static void
615interval_tree_rotate_left (struct itree_tree *tree, 515itree_rotate_left (struct itree_tree *tree,
616 struct itree_node *node) 516 struct itree_node *node)
617{ 517{
618 eassert (node->right != NULL); 518 eassert (node->right != NULL);
619 519
620 struct itree_node *right = node->right; 520 struct itree_node *right = node->right;
621 521
622 interval_tree_inherit_offset (tree->otick, node); 522 itree_inherit_offset (tree->otick, node);
623 interval_tree_inherit_offset (tree->otick, right); 523 itree_inherit_offset (tree->otick, right);
624 524
625 /* Turn right's left subtree into node's right subtree. */ 525 /* Turn right's left subtree into node's right subtree. */
626 node->right = right->left; 526 node->right = right->left;
@@ -648,22 +548,22 @@ interval_tree_rotate_left (struct itree_tree *tree,
648 node->parent = right; 548 node->parent = right;
649 549
650 /* Order matters here. */ 550 /* Order matters here. */
651 interval_tree_update_limit (node); 551 itree_update_limit (node);
652 interval_tree_update_limit (right); 552 itree_update_limit (right);
653} 553}
654 554
655/* Perform the familiar right-rotation on node NODE. */ 555/* Perform the familiar right-rotation on node NODE. */
656 556
657static void 557static void
658interval_tree_rotate_right (struct itree_tree *tree, 558itree_rotate_right (struct itree_tree *tree,
659 struct itree_node *node) 559 struct itree_node *node)
660{ 560{
661 eassert (tree && node && node->left != NULL); 561 eassert (tree && node && node->left != NULL);
662 562
663 struct itree_node *left = node->left; 563 struct itree_node *left = node->left;
664 564
665 interval_tree_inherit_offset (tree->otick, node); 565 itree_inherit_offset (tree->otick, node);
666 interval_tree_inherit_offset (tree->otick, left); 566 itree_inherit_offset (tree->otick, left);
667 567
668 node->left = left->right; 568 node->left = left->right;
669 if (left->right != NULL) 569 if (left->right != NULL)
@@ -685,8 +585,8 @@ interval_tree_rotate_right (struct itree_tree *tree,
685 if (node != NULL) 585 if (node != NULL)
686 node->parent = left; 586 node->parent = left;
687 587
688 interval_tree_update_limit (left); 588 itree_update_limit (left);
689 interval_tree_update_limit (node); 589 itree_update_limit (node);
690} 590}
691 591
692/* Repair the tree after an insertion. 592/* Repair the tree after an insertion.
@@ -694,7 +594,7 @@ interval_tree_rotate_right (struct itree_tree *tree,
694 Rebalance the parents as needed to re-establish the RB invariants. */ 594 Rebalance the parents as needed to re-establish the RB invariants. */
695 595
696static void 596static void
697interval_tree_insert_fix (struct itree_tree *tree, 597itree_insert_fix (struct itree_tree *tree,
698 struct itree_node *node) 598 struct itree_node *node)
699{ 599{
700 eassert (tree->root->red == false); 600 eassert (tree->root->red == false);
@@ -728,12 +628,12 @@ interval_tree_insert_fix (struct itree_tree *tree,
728 if (node == node->parent->right) /* case 2.a */ 628 if (node == node->parent->right) /* case 2.a */
729 { 629 {
730 node = node->parent; 630 node = node->parent;
731 interval_tree_rotate_left (tree, node); 631 itree_rotate_left (tree, node);
732 } 632 }
733 /* case 3.a */ 633 /* case 3.a */
734 node->parent->red = false; 634 node->parent->red = false;
735 node->parent->parent->red = true; 635 node->parent->parent->red = true;
736 interval_tree_rotate_right (tree, node->parent->parent); 636 itree_rotate_right (tree, node->parent->parent);
737 } 637 }
738 } 638 }
739 else 639 else
@@ -753,12 +653,12 @@ interval_tree_insert_fix (struct itree_tree *tree,
753 if (node == node->parent->left) /* case 2.b */ 653 if (node == node->parent->left) /* case 2.b */
754 { 654 {
755 node = node->parent; 655 node = node->parent;
756 interval_tree_rotate_right (tree, node); 656 itree_rotate_right (tree, node);
757 } 657 }
758 /* case 3.b */ 658 /* case 3.b */
759 node->parent->red = false; 659 node->parent->red = false;
760 node->parent->parent->red = true; 660 node->parent->parent->red = true;
761 interval_tree_rotate_left (tree, node->parent->parent); 661 itree_rotate_left (tree, node->parent->parent);
762 } 662 }
763 } 663 }
764 } 664 }
@@ -770,22 +670,20 @@ interval_tree_insert_fix (struct itree_tree *tree,
770} 670}
771 671
772/* Insert a NODE into the TREE. 672/* Insert a NODE into the TREE.
773 Note, that inserting a node twice results in undefined behaviour. */ 673 Note, that inserting a node twice results in undefined behavior. */
774 674
775static void 675static void
776interval_tree_insert (struct itree_tree *tree, struct itree_node *node) 676itree_insert_node (struct itree_tree *tree, struct itree_node *node)
777{ 677{
778 eassert (node->begin <= node->end && node != NULL); 678 eassert (node && node->begin <= node->end);
779 /* FIXME: The assertion below fails because `delete_all_overlays` 679 eassert (node->left == NULL && node->right == NULL
780 doesn't set left/right/parent to NULL. */ 680 && node->parent == NULL);
781 /* eassert (node->left == NULL && node->right == NULL
782 && node->parent == NULL) */;
783 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */ 681 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
784 682
785 struct itree_node *parent = NULL; 683 struct itree_node *parent = NULL;
786 struct itree_node *child = tree->root; 684 struct itree_node *child = tree->root;
787 uintmax_t otick = tree->otick; 685 uintmax_t otick = tree->otick;
788 /* It's the responsability of the caller to set `otick` on the node, 686 /* It's the responsibility of the caller to set `otick` on the node,
789 to "confirm" that the begin/end fields are up to date. */ 687 to "confirm" that the begin/end fields are up to date. */
790 eassert (node->otick == otick); 688 eassert (node->otick == otick);
791 689
@@ -793,7 +691,7 @@ interval_tree_insert (struct itree_tree *tree, struct itree_node *node)
793 ancestors limit values. */ 691 ancestors limit values. */
794 while (child != NULL) 692 while (child != NULL)
795 { 693 {
796 interval_tree_inherit_offset (otick, child); 694 itree_inherit_offset (otick, child);
797 parent = child; 695 parent = child;
798 eassert (child->offset == 0); 696 eassert (child->offset == 0);
799 child->limit = max (child->limit, node->end); 697 child->limit = max (child->limit, node->end);
@@ -826,7 +724,7 @@ interval_tree_insert (struct itree_tree *tree, struct itree_node *node)
826 { 724 {
827 node->red = true; 725 node->red = true;
828 eassert (check_tree (tree, false)); /* FIXME: Too expensive. */ 726 eassert (check_tree (tree, false)); /* FIXME: Too expensive. */
829 interval_tree_insert_fix (tree, node); 727 itree_insert_fix (tree, node);
830 } 728 }
831} 729}
832 730
@@ -837,7 +735,7 @@ itree_insert (struct itree_tree *tree, struct itree_node *node,
837 node->begin = begin; 735 node->begin = begin;
838 node->end = end; 736 node->end = end;
839 node->otick = tree->otick; 737 node->otick = tree->otick;
840 interval_tree_insert (tree, node); 738 itree_insert_node (tree, node);
841} 739}
842 740
843/* Safely modify a node's interval. */ 741/* Safely modify a node's interval. */
@@ -847,35 +745,32 @@ itree_node_set_region (struct itree_tree *tree,
847 struct itree_node *node, 745 struct itree_node *node,
848 ptrdiff_t begin, ptrdiff_t end) 746 ptrdiff_t begin, ptrdiff_t end)
849{ 747{
850 interval_tree_validate (tree, node); 748 itree_validate (tree, node);
851 if (begin != node->begin) 749 if (begin != node->begin)
852 { 750 {
853 itree_remove (tree, node); 751 itree_remove (tree, node);
854 node->begin = min (begin, PTRDIFF_MAX - 1); 752 node->begin = min (begin, PTRDIFF_MAX - 1);
855 node->end = max (node->begin, end); 753 node->end = max (node->begin, end);
856 interval_tree_insert (tree, node); 754 itree_insert_node (tree, node);
857 } 755 }
858 else if (end != node->end) 756 else if (end != node->end)
859 { 757 {
860 node->end = max (node->begin, end); 758 node->end = max (node->begin, end);
861 eassert (node != NULL); 759 eassert (node != NULL);
862 interval_tree_propagate_limit (node); 760 itree_propagate_limit (node);
863 } 761 }
864} 762}
865 763
866/* Return true, if NODE is a member of TREE. */ 764/* Return true, if NODE is a member of TREE. */
867 765
868static bool 766static bool
869interval_tree_contains (struct itree_tree *tree, struct itree_node *node) 767itree_contains (struct itree_tree *tree, struct itree_node *node)
870{ 768{
871 eassert (node); 769 eassert (node);
872 struct itree_node *other; 770 struct itree_node *other;
873 ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING) 771 ITREE_FOREACH (other, tree, node->begin, PTRDIFF_MAX, ASCENDING)
874 if (other == node) 772 if (other == node)
875 { 773 return true;
876 ITREE_FOREACH_ABORT ();
877 return true;
878 }
879 774
880 return false; 775 return false;
881} 776}
@@ -890,11 +785,11 @@ itree_limit_is_stable (struct itree_node *node)
890} 785}
891 786
892static struct itree_node* 787static struct itree_node*
893interval_tree_subtree_min (uintmax_t otick, struct itree_node *node) 788itree_subtree_min (uintmax_t otick, struct itree_node *node)
894{ 789{
895 if (node == NULL) 790 if (node == NULL)
896 return node; 791 return node;
897 while ((interval_tree_inherit_offset (otick, node), 792 while ((itree_inherit_offset (otick, node),
898 node->left != NULL)) 793 node->left != NULL))
899 node = node->left; 794 node = node->left;
900 return node; 795 return node;
@@ -905,14 +800,14 @@ interval_tree_subtree_min (uintmax_t otick, struct itree_node *node)
905 so re-balance the parents to re-establish the RB invariants. */ 800 so re-balance the parents to re-establish the RB invariants. */
906 801
907static void 802static void
908interval_tree_remove_fix (struct itree_tree *tree, 803itree_remove_fix (struct itree_tree *tree,
909 struct itree_node *node, 804 struct itree_node *node,
910 struct itree_node *parent) 805 struct itree_node *parent)
911{ 806{
912 if (parent == NULL) 807 if (parent == NULL)
913 eassert (node == tree->root); 808 eassert (node == tree->root);
914 else 809 else
915 eassert (node == NULL || node->parent == parent); 810 eassert (node == NULL || node->parent == parent);
916 811
917 while (parent != NULL && null_safe_is_black (node)) 812 while (parent != NULL && null_safe_is_black (node))
918 { 813 {
@@ -926,7 +821,7 @@ interval_tree_remove_fix (struct itree_tree *tree,
926 { 821 {
927 other->red = false; 822 other->red = false;
928 parent->red = true; 823 parent->red = true;
929 interval_tree_rotate_left (tree, parent); 824 itree_rotate_left (tree, parent);
930 other = parent->right; 825 other = parent->right;
931 } 826 }
932 eassume (other != NULL); 827 eassume (other != NULL);
@@ -945,13 +840,13 @@ interval_tree_remove_fix (struct itree_tree *tree,
945 { 840 {
946 other->left->red = false; 841 other->left->red = false;
947 other->red = true; 842 other->red = true;
948 interval_tree_rotate_right (tree, other); 843 itree_rotate_right (tree, other);
949 other = parent->right; 844 other = parent->right;
950 } 845 }
951 other->red = parent->red; /* 4.a */ 846 other->red = parent->red; /* 4.a */
952 parent->red = false; 847 parent->red = false;
953 other->right->red = false; 848 other->right->red = false;
954 interval_tree_rotate_left (tree, parent); 849 itree_rotate_left (tree, parent);
955 node = tree->root; 850 node = tree->root;
956 parent = NULL; 851 parent = NULL;
957 } 852 }
@@ -964,7 +859,7 @@ interval_tree_remove_fix (struct itree_tree *tree,
964 { 859 {
965 other->red = false; 860 other->red = false;
966 parent->red = true; 861 parent->red = true;
967 interval_tree_rotate_right (tree, parent); 862 itree_rotate_right (tree, parent);
968 other = parent->left; 863 other = parent->left;
969 } 864 }
970 eassume (other != NULL); 865 eassume (other != NULL);
@@ -983,14 +878,14 @@ interval_tree_remove_fix (struct itree_tree *tree,
983 { 878 {
984 other->right->red = false; 879 other->right->red = false;
985 other->red = true; 880 other->red = true;
986 interval_tree_rotate_left (tree, other); 881 itree_rotate_left (tree, other);
987 other = parent->left; 882 other = parent->left;
988 } 883 }
989 884
990 other->red = parent->red; /* 4.b */ 885 other->red = parent->red; /* 4.b */
991 parent->red = false; 886 parent->red = false;
992 other->left->red = false; 887 other->left->red = false;
993 interval_tree_rotate_right (tree, parent); 888 itree_rotate_right (tree, parent);
994 node = tree->root; 889 node = tree->root;
995 parent = NULL; 890 parent = NULL;
996 } 891 }
@@ -1023,7 +918,7 @@ itree_total_offset (struct itree_node *node)
1023 unchanged. Caller is responsible for recalculation of `limit`. 918 unchanged. Caller is responsible for recalculation of `limit`.
1024 Requires both nodes to be using the same effective `offset`. */ 919 Requires both nodes to be using the same effective `offset`. */
1025static void 920static void
1026interval_tree_replace_child (struct itree_tree *tree, 921itree_replace_child (struct itree_tree *tree,
1027 struct itree_node *source, 922 struct itree_node *source,
1028 struct itree_node *dest) 923 struct itree_node *dest)
1029{ 924{
@@ -1049,11 +944,11 @@ interval_tree_replace_child (struct itree_tree *tree,
1049 recalculation of `limit`. Requires both nodes to be using the same 944 recalculation of `limit`. Requires both nodes to be using the same
1050 effective `offset`. */ 945 effective `offset`. */
1051static void 946static void
1052interval_tree_transplant (struct itree_tree *tree, 947itree_transplant (struct itree_tree *tree,
1053 struct itree_node *source, 948 struct itree_node *source,
1054 struct itree_node *dest) 949 struct itree_node *dest)
1055{ 950{
1056 interval_tree_replace_child (tree, source, dest); 951 itree_replace_child (tree, source, dest);
1057 source->left = dest->left; 952 source->left = dest->left;
1058 if (source->left != NULL) 953 if (source->left != NULL)
1059 source->left->parent = source; 954 source->left->parent = source;
@@ -1068,17 +963,17 @@ interval_tree_transplant (struct itree_tree *tree,
1068struct itree_node* 963struct itree_node*
1069itree_remove (struct itree_tree *tree, struct itree_node *node) 964itree_remove (struct itree_tree *tree, struct itree_node *node)
1070{ 965{
1071 eassert (interval_tree_contains (tree, node)); 966 eassert (itree_contains (tree, node));
1072 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */ 967 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
1073 968
1074 /* Find `splice`, the leaf node to splice out of the tree. When 969 /* Find `splice`, the leaf node to splice out of the tree. When
1075 `node` has at most one child this is `node` itself. Otherwise, 970 `node` has at most one child this is `node` itself. Otherwise,
1076 it is the in order successor of `node`. */ 971 it is the in order successor of `node`. */
1077 interval_tree_inherit_offset (tree->otick, node); 972 itree_inherit_offset (tree->otick, node);
1078 struct itree_node *splice 973 struct itree_node *splice
1079 = (node->left == NULL || node->right == NULL) 974 = (node->left == NULL || node->right == NULL)
1080 ? node 975 ? node
1081 : interval_tree_subtree_min (tree->otick, node->right); 976 : itree_subtree_min (tree->otick, node->right);
1082 977
1083 /* Find `subtree`, the only child of `splice` (may be NULL). Note: 978 /* Find `subtree`, the only child of `splice` (may be NULL). Note:
1084 `subtree` will not be modified other than changing its parent to 979 `subtree` will not be modified other than changing its parent to
@@ -1099,7 +994,7 @@ itree_remove (struct itree_tree *tree, struct itree_node *node)
1099 `splice` is black, this creates a red-red violation, so remember 994 `splice` is black, this creates a red-red violation, so remember
1100 this now as the field can be overwritten when splice is 995 this now as the field can be overwritten when splice is
1101 transplanted below. */ 996 transplanted below. */
1102 interval_tree_replace_child (tree, subtree, splice); 997 itree_replace_child (tree, subtree, splice);
1103 bool removed_black = !splice->red; 998 bool removed_black = !splice->red;
1104 999
1105 /* Replace `node` with `splice` in the tree and propagate limit 1000 /* Replace `node` with `splice` in the tree and propagate limit
@@ -1108,18 +1003,18 @@ itree_remove (struct itree_tree *tree, struct itree_node *node)
1108 has a new child. */ 1003 has a new child. */
1109 if (splice != node) 1004 if (splice != node)
1110 { 1005 {
1111 interval_tree_transplant (tree, splice, node); 1006 itree_transplant (tree, splice, node);
1112 interval_tree_propagate_limit (subtree_parent); 1007 itree_propagate_limit (subtree_parent);
1113 if (splice != subtree_parent) 1008 if (splice != subtree_parent)
1114 interval_tree_update_limit (splice); 1009 itree_update_limit (splice);
1115 } 1010 }
1116 interval_tree_propagate_limit (splice->parent); 1011 itree_propagate_limit (splice->parent);
1117 1012
1118 --tree->size; 1013 --tree->size;
1119 1014
1120 /* Fix any black height violation caused by removing a black node. */ 1015 /* Fix any black height violation caused by removing a black node. */
1121 if (removed_black) 1016 if (removed_black)
1122 interval_tree_remove_fix (tree, subtree, subtree_parent); 1017 itree_remove_fix (tree, subtree, subtree_parent);
1123 1018
1124 eassert ((tree->size == 0) == (tree->root == NULL)); 1019 eassert ((tree->size == 0) == (tree->root == NULL));
1125 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */ 1020 eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
@@ -1137,52 +1032,6 @@ itree_remove (struct itree_tree *tree, struct itree_node *node)
1137 return node; 1032 return node;
1138} 1033}
1139 1034
1140bool
1141itree_iterator_busy_p (void)
1142{
1143 return (iter && iter->running);
1144}
1145
1146/* Start a iterator enumerating all intervals in [BEGIN,END) in the
1147 given ORDER. Only one iterator per tree can be running at any time. */
1148
1149struct itree_iterator *
1150itree_iterator_start (struct itree_tree *tree, ptrdiff_t begin,
1151 ptrdiff_t end, enum itree_order order,
1152 const char *file, int line)
1153{
1154 /* struct itree_iterator *iter = tree->iter; */
1155 if (iter->running)
1156 {
1157 fprintf (stderr,
1158 "Detected nested iteration!\nOuter: %s:%d\nInner: %s:%d\n",
1159 iter->file, iter->line, file, line);
1160 emacs_abort ();
1161 }
1162 iter->begin = begin;
1163 iter->end = end;
1164 iter->otick = tree->otick;
1165 iter->order = order;
1166 interval_stack_clear (iter->stack);
1167 if (begin <= end && tree->root != NULL)
1168 interval_stack_push_flagged (iter->stack, tree->root, false);
1169 iter->file = file;
1170 iter->line = line;
1171 iter->running = true;
1172 /* interval_stack_ensure_space (iter->stack,
1173 2 * interval_tree_max_height (tree)); */
1174 return iter;
1175}
1176
1177/* Stop using the iterator. */
1178
1179void
1180itree_iterator_finish (struct itree_iterator *iter)
1181{
1182 eassert (iter->running);
1183 iter->running = false;
1184}
1185
1186 1035
1187/* +=======================================================================+ 1036/* +=======================================================================+
1188 * | Insert/Delete Gaps 1037 * | Insert/Delete Gaps
@@ -1190,113 +1039,125 @@ itree_iterator_finish (struct itree_iterator *iter)
1190 1039
1191/* Insert a gap at POS of length LENGTH expanding all intervals 1040/* Insert a gap at POS of length LENGTH expanding all intervals
1192 intersecting it, while respecting their rear_advance and 1041 intersecting it, while respecting their rear_advance and
1193 front_advance setting. */ 1042 front_advance setting.
1043
1044 If BEFORE_MARKERS is non-zero, all overlays beginning/ending at POS
1045 are treated as if their front_advance/rear_advance was true. */
1194 1046
1195void 1047void
1196itree_insert_gap (struct itree_tree *tree, 1048itree_insert_gap (struct itree_tree *tree,
1197 ptrdiff_t pos, ptrdiff_t length) 1049 ptrdiff_t pos, ptrdiff_t length, bool before_markers)
1198{ 1050{
1199 if (length <= 0 || tree->root == NULL) 1051 if (!tree || length <= 0 || tree->root == NULL)
1200 return; 1052 return;
1201 uintmax_t ootick = tree->otick; 1053 uintmax_t ootick = tree->otick;
1202 1054
1203 /* FIXME: Don't allocate iterator/stack anew every time. */ 1055 /* FIXME: Don't allocate iterator/stack anew every time. */
1204 1056
1205 /* Nodes with front_advance starting at pos may mess up the tree 1057 /* Nodes with front_advance starting at pos may mess up the tree
1206 order, so we need to remove them first. */ 1058 order, so we need to remove them first. This doesn't apply for
1207 struct interval_stack *saved = interval_stack_create (0); 1059 `before_markers` since in that case, all positions move identically
1060 regardless of `front_advance` or `rear_advance`. */
1061 struct itree_stack *saved = itree_stack_create (0);
1208 struct itree_node *node = NULL; 1062 struct itree_node *node = NULL;
1209 ITREE_FOREACH (node, tree, pos, pos + 1, PRE_ORDER) 1063 if (!before_markers)
1210 { 1064 {
1211 if (node->begin == pos && node->front_advance 1065 /* Actually any order would do. */
1212 && (node->begin != node->end || node->rear_advance)) 1066 ITREE_FOREACH (node, tree, pos, pos + 1, PRE_ORDER)
1213 interval_stack_push (saved, node); 1067 {
1068 if (node->begin == pos && node->front_advance
1069 /* If we have front_advance and !rear_advance and
1070 the overlay is empty, make sure we don't move
1071 begin past end by pretending it's !front_advance. */
1072 && (node->begin != node->end || node->rear_advance))
1073 itree_stack_push (saved, node);
1074 }
1214 } 1075 }
1215 for (int i = 0; i < saved->length; ++i) 1076 for (size_t i = 0; i < saved->length; ++i)
1216 itree_remove (tree, nav_nodeptr (saved->nodes[i])); 1077 itree_remove (tree, saved->nodes[i]);
1217 1078
1218 /* We can't use an iterator here, because we can't effectively 1079 /* We can't use an iterator here, because we can't effectively
1219 narrow AND shift some subtree at the same time. */ 1080 narrow AND shift some subtree at the same time. */
1220 if (tree->root != NULL) 1081 if (tree->root != NULL)
1221 { 1082 {
1222 const int size = interval_tree_max_height (tree) + 1; 1083 const int size = itree_max_height (tree) + 1;
1223 struct interval_stack *stack = interval_stack_create (size); 1084 struct itree_stack *stack = itree_stack_create (size);
1224 interval_stack_push (stack, tree->root); 1085 itree_stack_push (stack, tree->root);
1225 nodeptr_and_flag nav; 1086 while ((node = itree_stack_pop (stack)))
1226 while ((nav = interval_stack_pop (stack),
1227 node = nav_nodeptr (nav)))
1228 { 1087 {
1229 /* Process in pre-order. */ 1088 /* Process in pre-order. */
1230 interval_tree_inherit_offset (tree->otick, node); 1089 itree_inherit_offset (tree->otick, node);
1090 if (pos > node->limit)
1091 continue;
1231 if (node->right != NULL) 1092 if (node->right != NULL)
1232 { 1093 {
1233 if (node->begin > pos) 1094 if (node->begin > pos)
1234 { 1095 {
1235 /* All nodes in this subtree are shifted by length. */ 1096 /* All nodes in this subtree are shifted by length. */
1236 node->right->offset += length; 1097 node->right->offset += length;
1237 ++tree->otick; 1098 ++tree->otick;
1238 } 1099 }
1239 else 1100 else
1240 interval_stack_push (stack, node->right); 1101 itree_stack_push (stack, node->right);
1241 } 1102 }
1242 if (node->left != NULL 1103 if (node->left != NULL)
1243 && pos <= node->left->limit + node->left->offset) 1104 itree_stack_push (stack, node->left);
1244 interval_stack_push (stack, node->left);
1245 1105
1246 /* node->begin == pos implies no front-advance. */ 1106 if (before_markers
1247 if (node->begin > pos) 1107 ? node->begin >= pos
1108 : node->begin > pos) /* node->begin == pos => !front-advance */
1248 node->begin += length; 1109 node->begin += length;
1249 if (node->end > pos || (node->end == pos && node->rear_advance)) 1110 if (node->end > pos
1111 || (node->end == pos && (before_markers || node->rear_advance)))
1250 { 1112 {
1251 node->end += length; 1113 node->end += length;
1252 eassert (node != NULL); 1114 eassert (node != NULL);
1253 interval_tree_propagate_limit (node); 1115 itree_propagate_limit (node);
1254 } 1116 }
1255 } 1117 }
1256 interval_stack_destroy (stack); 1118 itree_stack_destroy (stack);
1257 } 1119 }
1258 1120
1259 /* Reinsert nodes starting at POS having front-advance. */ 1121 /* Reinsert nodes starting at POS having front-advance. */
1260 uintmax_t notick = tree->otick; 1122 uintmax_t notick = tree->otick;
1261 nodeptr_and_flag nav; 1123 while ((node = itree_stack_pop (saved)))
1262 while ((nav = interval_stack_pop (saved),
1263 node = nav_nodeptr (nav)))
1264 { 1124 {
1265 eassert (node->otick == ootick); 1125 eassert (node->otick == ootick);
1126 eassert (node->begin == pos);
1127 eassert (node->end > pos || node->rear_advance);
1266 node->begin += length; 1128 node->begin += length;
1267 if (node->end != pos || node->rear_advance) 1129 node->end += length;
1268 node->end += length;
1269 node->otick = notick; 1130 node->otick = notick;
1270 interval_tree_insert (tree, node); 1131 itree_insert_node (tree, node);
1271 } 1132 }
1272 1133
1273 interval_stack_destroy (saved); 1134 itree_stack_destroy (saved);
1274} 1135}
1275 1136
1276/* Delete a gap at POS of length LENGTH, contracting all intervals 1137/* Delete a gap at POS of length LENGTH, contracting all intervals
1277 intersecting it. */ 1138 intersecting it. */
1278 1139
1279void 1140void
1280itree_delete_gap (struct itree_tree *tree, 1141itree_delete_gap (struct itree_tree *tree,
1281 ptrdiff_t pos, ptrdiff_t length) 1142 ptrdiff_t pos, ptrdiff_t length)
1282{ 1143{
1283 if (length <= 0 || tree->root == NULL) 1144 if (!tree || length <= 0 || tree->root == NULL)
1284 return; 1145 return;
1285 1146
1286 /* FIXME: Don't allocate stack anew every time. */ 1147 /* FIXME: Don't allocate stack anew every time. */
1287 1148
1288 /* Can't use the iterator here, because by decrementing begin, we 1149 /* Can't use the iterator here, because by decrementing begin, we
1289 might unintentionally bring shifted nodes back into our search space. */ 1150 might unintentionally bring shifted nodes back into our search space. */
1290 const int size = interval_tree_max_height (tree) + 1; 1151 const int size = itree_max_height (tree) + 1;
1291 struct interval_stack *stack = interval_stack_create (size); 1152 struct itree_stack *stack = itree_stack_create (size);
1292 struct itree_node *node; 1153 struct itree_node *node;
1293 1154
1294 interval_stack_push (stack, tree->root); 1155 itree_stack_push (stack, tree->root);
1295 nodeptr_and_flag nav; 1156 while ((node = itree_stack_pop (stack)))
1296 while ((nav = interval_stack_pop (stack)))
1297 { 1157 {
1298 node = nav_nodeptr (nav); 1158 itree_inherit_offset (tree->otick, node);
1299 interval_tree_inherit_offset (tree->otick, node); 1159 if (pos > node->limit)
1160 continue;
1300 if (node->right != NULL) 1161 if (node->right != NULL)
1301 { 1162 {
1302 if (node->begin > pos + length) 1163 if (node->begin > pos + length)
@@ -1306,11 +1167,10 @@ itree_delete_gap (struct itree_tree *tree,
1306 ++tree->otick; 1167 ++tree->otick;
1307 } 1168 }
1308 else 1169 else
1309 interval_stack_push (stack, node->right); 1170 itree_stack_push (stack, node->right);
1310 } 1171 }
1311 if (node->left != NULL 1172 if (node->left != NULL)
1312 && pos <= node->left->limit + node->left->offset) 1173 itree_stack_push (stack, node->left);
1313 interval_stack_push (stack, node->left);
1314 1174
1315 if (pos < node->begin) 1175 if (pos < node->begin)
1316 node->begin = max (pos, node->begin - length); 1176 node->begin = max (pos, node->begin - length);
@@ -1318,10 +1178,10 @@ itree_delete_gap (struct itree_tree *tree,
1318 { 1178 {
1319 node->end = max (pos , node->end - length); 1179 node->end = max (pos , node->end - length);
1320 eassert (node != NULL); 1180 eassert (node != NULL);
1321 interval_tree_propagate_limit (node); 1181 itree_propagate_limit (node);
1322 } 1182 }
1323 } 1183 }
1324 interval_stack_destroy (stack); 1184 itree_stack_destroy (stack);
1325} 1185}
1326 1186
1327 1187
@@ -1339,81 +1199,217 @@ itree_delete_gap (struct itree_tree *tree,
1339 a NODE2 strictly bigger than NODE1 should also be included). */ 1199 a NODE2 strictly bigger than NODE1 should also be included). */
1340 1200
1341static inline bool 1201static inline bool
1342interval_node_intersects (const struct itree_node *node, 1202itree_node_intersects (const struct itree_node *node,
1343 ptrdiff_t begin, ptrdiff_t end) 1203 ptrdiff_t begin, ptrdiff_t end)
1344{ 1204{
1345 return (begin < node->end && node->begin < end) 1205 return (begin < node->end && node->begin < end)
1346 || (node->begin == node->end && begin == node->begin); 1206 || (node->begin == node->end && begin == node->begin);
1347} 1207}
1348 1208
1349/* Return the next node of the iterator in the order given when it was 1209/* Return the "next" node in the current traversal order.
1350 started; or NULL if there are no more nodes. */
1351 1210
1352struct itree_node * 1211 Note that this should return all the nodes that we need to traverse
1353itree_iterator_next (struct itree_iterator *g) 1212 in order to traverse the nodes selected by the current narrowing (i.e.
1354{ 1213 `ITER->begin..ITER->end`) so it will also return some nodes which aren't in
1355 eassert (g->running); 1214 that narrowing simply because they may have children which are.
1356 1215
1357 struct itree_node *const null = NULL; 1216 The code itself is very unsatifactory because the code of each one
1358 struct itree_node *node; 1217 of the supported traversals seems completely different from the others.
1218 If someone knows how to make it more uniform and "obviously correct",
1219 please make yourself heard. */
1359 1220
1360 /* The `visited` flag stored in each node is used here (and only here): 1221static struct itree_node *
1361 We keep a "workstack" of nodes we need to consider. This stack 1222itree_iter_next_in_subtree (struct itree_node *node,
1362 consist of nodes of two types: nodes that we have decided 1223 struct itree_iterator *iter)
1363 should be returned by the iterator, and nodes which we may 1224{
1364 need to consider (including checking their children). 1225 /* FIXME: Like in the previous version of the iterator, we
1365 We start an iteration with a stack containing just the root 1226 prune based on `limit` only when moving to a left child,
1366 node marked as "not visited" which means that it (and its children) 1227 but `limit` can also get smaller when moving to a right child
1367 needs to be considered but we haven't yet decided whether it's included 1228 It's actually fairly common, so maybe it would be worthwhile
1368 in the iterator's output. */ 1229 to prune a bit more aggressively here. */
1369 1230 struct itree_node *next;
1370 do 1231 switch (iter->order)
1371 { 1232 {
1372 nodeptr_and_flag nav; 1233 case ITREE_ASCENDING:
1373 bool visited; 1234 next = node->right;
1374 while ((nav = interval_stack_pop (g->stack), 1235 if (!next)
1375 node = nav_nodeptr (nav), 1236 {
1376 visited = nav_flag (nav), 1237 while ((next = node->parent)
1377 node && !visited)) 1238 && next->right == node)
1378 { 1239 node = next;
1379 struct itree_node *const left = node->left; 1240 if (!next)
1380 struct itree_node *const right = node->right; 1241 return NULL; /* No more nodes to visit. */
1242 node = next;
1243 }
1244 else
1245 {
1246 node = next;
1247 itree_inherit_offset (iter->otick, node);
1248 while ((next = node->left)
1249 && (itree_inherit_offset (iter->otick, next),
1250 iter->begin <= next->limit))
1251 node = next;
1252 }
1253 if (node->begin > iter->end)
1254 return NULL; /* No more nodes within begin..end. */
1255 return node;
1256
1257 case ITREE_DESCENDING:
1258 next = node->left;
1259 if (!next
1260 || (itree_inherit_offset (iter->otick, next),
1261 next->limit < iter->begin))
1262 {
1263 while ((next = node->parent)
1264 && next->left == node)
1265 node = next;
1266 if (!next)
1267 return NULL; /* No more nodes to visit. */
1268 node = next;
1269 }
1270 else
1271 {
1272 node = next;
1273 while (node->begin <= iter->end
1274 && (next = node->right))
1275 {
1276 itree_inherit_offset (iter->otick, next),
1277 node = next;
1278 }
1279 }
1280 return node;
1281
1282 case ITREE_PRE_ORDER:
1283 next = node->left;
1284 if (next
1285 && (itree_inherit_offset (iter->otick, next),
1286 !(next->limit < iter->begin)))
1287 return next;
1288 next = node->right;
1289 if (node->begin <= iter->end && next)
1290 {
1291 itree_inherit_offset (iter->otick, next);
1292 return next;
1293 }
1294 while ((next = node->parent))
1295 {
1296 if (next->right == node)
1297 node = next;
1298 else
1299 {
1300 eassert (next->left == node);
1301 node = next;
1302 next = node->right;
1303 if (node->begin <= iter->end && next)
1304 {
1305 itree_inherit_offset (iter->otick, next);
1306 return next;
1307 }
1308 }
1309 }
1310 return NULL;
1311
1312 case ITREE_POST_ORDER:
1313 next = node->parent;
1314 if (!next || next->right == node)
1315 return next;
1316 eassert (next->left == node);
1317 node = next;
1318 next = node->right;
1319 if (!(node->begin <= iter->end && next))
1320 return node;
1321 node = next;
1322 itree_inherit_offset (iter->otick, node);
1323 while (((next = node->left)
1324 && (itree_inherit_offset (iter->otick, next),
1325 iter->begin <= next->limit))
1326 || (node->begin <= iter->end
1327 && (next = node->right)
1328 && (itree_inherit_offset (iter->otick, next), true)))
1329 node = next;
1330 return node;
1331
1332 default:
1333 emacs_abort ();
1334 }
1335}
1381 1336
1382 interval_tree_inherit_offset (g->otick, node); 1337static struct itree_node *
1383 eassert (itree_limit_is_stable (node)); 1338itree_iterator_first_node (struct itree_tree *tree,
1384 switch (g->order) 1339 struct itree_iterator *iter)
1385 { 1340{
1386 case ITREE_ASCENDING: 1341 struct itree_node *node = tree->root;
1387 if (right != null && node->begin <= g->end) 1342 if (node)
1388 interval_stack_push_flagged (g->stack, right, false); 1343 {
1389 if (interval_node_intersects (node, g->begin, g->end)) 1344 struct itree_node dummy;
1390 interval_stack_push_flagged (g->stack, node, true); 1345 dummy.left = NULL;
1391 /* Node's children may still be off-set and we need to add it. */ 1346 dummy.parent = NULL;
1392 if (left != null && g->begin <= left->limit + left->offset) 1347 dummy.right = NULL;
1393 interval_stack_push_flagged (g->stack, left, false); 1348 itree_inherit_offset (iter->otick, node);
1394 break; 1349 switch (iter->order)
1395 case ITREE_DESCENDING: 1350 {
1396 if (left != null && g->begin <= left->limit + left->offset) 1351 case ITREE_ASCENDING:
1397 interval_stack_push_flagged (g->stack, left, false); 1352 dummy.right = node;
1398 if (interval_node_intersects (node, g->begin, g->end)) 1353 dummy.begin = PTRDIFF_MIN;
1399 interval_stack_push_flagged (g->stack, node, true); 1354 node = itree_iter_next_in_subtree (&dummy, iter);
1400 if (right != null && node->begin <= g->end) 1355 break;
1401 interval_stack_push_flagged (g->stack, right, false); 1356
1402 break; 1357 case ITREE_DESCENDING:
1403 case ITREE_PRE_ORDER: 1358 dummy.left = node;
1404 if (right != null && node->begin <= g->end) 1359 node = itree_iter_next_in_subtree (&dummy, iter);
1405 interval_stack_push_flagged (g->stack, right, false); 1360 break;
1406 if (left != null && g->begin <= left->limit + left->offset) 1361
1407 interval_stack_push_flagged (g->stack, left, false); 1362 case ITREE_PRE_ORDER:
1408 if (interval_node_intersects (node, g->begin, g->end)) 1363 break;
1409 interval_stack_push_flagged (g->stack, node, true); 1364
1410 break; 1365 case ITREE_POST_ORDER:
1411 } 1366 dummy.parent = &dummy;
1412 } 1367 dummy.left = &dummy;
1413 /* Node may have been invalidated by itree_iterator_narrow 1368 dummy.right = node;
1414 after it was pushed: Check if it still intersects. */ 1369 dummy.begin = PTRDIFF_MIN;
1415 } while (node && ! interval_node_intersects (node, g->begin, g->end)); 1370 node = itree_iter_next_in_subtree (&dummy, iter);
1371 break;
1372 default:
1373 emacs_abort ();
1374 }
1375 }
1376 return node;
1377}
1378
1379/* Start a iterator enumerating all intervals in [BEGIN,END) in the
1380 given ORDER. */
1381
1382struct itree_iterator *
1383itree_iterator_start (struct itree_iterator *iter,
1384 struct itree_tree *tree,
1385 ptrdiff_t begin, ptrdiff_t end, enum itree_order order)
1386{
1387 eassert (iter);
1388 iter->begin = begin;
1389 iter->end = end;
1390 iter->otick = tree->otick;
1391 iter->order = order;
1392 /* Beware: the `node` field always holds "the next" node to consider.
1393 so it's always "one node ahead" of what the iterator loop sees.
1394 In most respects this makes no difference, but we depend on this
1395 detail in `delete_all_overlays` where this allows us to modify
1396 the current node knowing that the iterator will not need it to
1397 find the next. */
1398 iter->node = itree_iterator_first_node (tree, iter);
1399 return iter;
1400}
1416 1401
1402struct itree_node *
1403itree_iterator_next (struct itree_iterator *iter)
1404{
1405 struct itree_node *node = iter->node;
1406 while (node
1407 && !itree_node_intersects (node, iter->begin, iter->end))
1408 {
1409 node = itree_iter_next_in_subtree (node, iter);
1410 eassert (itree_limit_is_stable (node));
1411 }
1412 iter->node = node ? itree_iter_next_in_subtree (node, iter) : NULL;
1417 return node; 1413 return node;
1418} 1414}
1419 1415
@@ -1424,9 +1420,9 @@ void
1424itree_iterator_narrow (struct itree_iterator *g, 1420itree_iterator_narrow (struct itree_iterator *g,
1425 ptrdiff_t begin, ptrdiff_t end) 1421 ptrdiff_t begin, ptrdiff_t end)
1426{ 1422{
1427 eassert (g->running); 1423 eassert (g);
1428 eassert (begin >= g->begin); 1424 eassert (begin >= g->begin);
1429 eassert (end <= g->end); 1425 eassert (end <= g->end);
1430 g->begin = max (begin, g->begin); 1426 g->begin = max (begin, g->begin);
1431 g->end = min (end, g->end); 1427 g->end = min (end, g->end);
1432} 1428}
diff --git a/src/itree.h b/src/itree.h
index c6b68d36672..291fa53fd30 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -104,6 +104,7 @@ enum itree_order
104 ITREE_ASCENDING, 104 ITREE_ASCENDING,
105 ITREE_DESCENDING, 105 ITREE_DESCENDING,
106 ITREE_PRE_ORDER, 106 ITREE_PRE_ORDER,
107 ITREE_POST_ORDER,
107 }; 108 };
108 109
109extern void itree_node_init (struct itree_node *, bool, bool, Lisp_Object); 110extern void itree_node_init (struct itree_node *, bool, bool, Lisp_Object);
@@ -119,25 +120,33 @@ extern void itree_insert (struct itree_tree *, struct itree_node *,
119 ptrdiff_t, ptrdiff_t); 120 ptrdiff_t, ptrdiff_t);
120extern struct itree_node *itree_remove (struct itree_tree *, 121extern struct itree_node *itree_remove (struct itree_tree *,
121 struct itree_node *); 122 struct itree_node *);
122extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); 123extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t, bool);
123extern void itree_delete_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); 124extern void itree_delete_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t);
124 125
125/* Iteration functions. Almost all code should use ITREE_FOREACH 126/* Iteration functions. Almost all code should use ITREE_FOREACH
126 instead. */ 127 instead. */
127extern bool itree_iterator_busy_p (void); 128extern struct itree_iterator *itree_iterator_start (struct itree_iterator *,
128extern struct itree_iterator *itree_iterator_start (struct itree_tree *, 129 struct itree_tree *,
129 ptrdiff_t, 130 ptrdiff_t,
130 ptrdiff_t, 131 ptrdiff_t,
131 enum itree_order, 132 enum itree_order);
132 const char *, int);
133extern void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t, 133extern void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t,
134 ptrdiff_t); 134 ptrdiff_t);
135extern void itree_iterator_finish (struct itree_iterator *);
136extern struct itree_node *itree_iterator_next (struct itree_iterator *); 135extern struct itree_node *itree_iterator_next (struct itree_iterator *);
137 136
137/* State used when iterating interval. */
138struct itree_iterator
139 {
140 struct itree_node *node;
141 ptrdiff_t begin;
142 ptrdiff_t end;
143 uintmax_t otick; /* A copy of the tree's `otick`. */
144 enum itree_order order;
145 };
146
138/* Iterate over the intervals between BEG and END in the tree T. 147/* Iterate over the intervals between BEG and END in the tree T.
139 N will hold successive nodes. ORDER can be one of : `ASCENDING`, 148 N will hold successive nodes. ORDER can be one of : `ASCENDING`,
140 `DESCENDING`, or `PRE_ORDER`. 149 `DESCENDING`, `POST_ORDER`, or `PRE_ORDER`.
141 It should be used as: 150 It should be used as:
142 151
143 ITREE_FOREACH (n, t, beg, end, order) 152 ITREE_FOREACH (n, t, beg, end, order)
@@ -147,34 +156,24 @@ extern struct itree_node *itree_iterator_next (struct itree_iterator *);
147 156
148 BEWARE: 157 BEWARE:
149 - The expression T may be evaluated more than once, so make sure 158 - The expression T may be evaluated more than once, so make sure
150 it is cheap a pure. 159 it is cheap and pure.
151 - Only a single iteration can happen at a time, so make sure none of the
152 code within the loop can start another tree iteration, i.e. it shouldn't
153 be able to run ELisp code, nor GC since GC can run ELisp by way
154 of `post-gc-hook`.
155 - If you need to exit the loop early, you *have* to call `ITREE_ABORT`
156 just before exiting (e.g. with `break` or `return`).
157 - Non-local exits are not supported within the body of the loop.
158 - Don't modify the tree during the iteration. 160 - Don't modify the tree during the iteration.
159 */ 161 */
160#define ITREE_FOREACH(n, t, beg, end, order) \ 162#define ITREE_FOREACH(n, t, beg, end, order) \
161 /* FIXME: We'd want to declare `x` right here, but I can't figure out 163 /* FIXME: We'd want to declare `n` right here, but I can't figure out
162 how to make that work here: the `for` syntax only allows a single 164 how to make that work here: the `for` syntax only allows a single
163 clause for the var declarations where we need 2 different types. 165 clause for the var declarations where we need 2 different types.
164 We could use the `struct {foo x; bar y; } p;` trick to declare two 166 We could use the `struct {foo x; bar y; } p;` trick to declare two
165 vars `p.x` and `p.y` of unrelated types, but then none of the names 167 vars `p.x` and `p.y` of unrelated types, but then none of the names
166 of the vars matches the `n` we receive :-(. */ \ 168 of the vars matches the `n` we receive :-(. */ \
167 if (!t) \ 169 if (!t) \
168 { } \ 170 { } \
169 else \ 171 else \
170 for (struct itree_iterator *itree_iter_ \ 172 for (struct itree_iterator itree_local_iter_, \
171 = itree_iterator_start (t, beg, end, ITREE_##order, \ 173 *itree_iter_ \
172 __FILE__, __LINE__); \ 174 = itree_iterator_start (&itree_local_iter_, \
173 ((n = itree_iterator_next (itree_iter_)) \ 175 t, beg, end, ITREE_##order); \
174 || (itree_iterator_finish (itree_iter_), false));) 176 ((n = itree_iterator_next (itree_iter_)));)
175
176#define ITREE_FOREACH_ABORT() \
177 itree_iterator_finish (itree_iter_)
178 177
179#define ITREE_FOREACH_NARROW(beg, end) \ 178#define ITREE_FOREACH_NARROW(beg, end) \
180 itree_iterator_narrow (itree_iter_, beg, end) 179 itree_iterator_narrow (itree_iter_, beg, end)
diff --git a/src/keyboard.c b/src/keyboard.c
index d8796569cd2..4b35a044eb0 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -503,9 +503,11 @@ echo_add_key (Lisp_Object c)
503 if ((NILP (echo_string) || SCHARS (echo_string) == 0) 503 if ((NILP (echo_string) || SCHARS (echo_string) == 0)
504 && help_char_p (c)) 504 && help_char_p (c))
505 { 505 {
506 AUTO_STRING (str, " (Type ? for further options)"); 506 AUTO_STRING (str, " (Type ? for further options, q for quick help)");
507 AUTO_LIST2 (props, Qface, Qhelp_key_binding); 507 AUTO_LIST2 (props, Qface, Qhelp_key_binding);
508 Fadd_text_properties (make_fixnum (7), make_fixnum (8), props, str); 508 Fadd_text_properties (make_fixnum (7), make_fixnum (8), props, str);
509 Fadd_text_properties (make_fixnum (30), make_fixnum (31), props,
510str);
509 new_string = concat2 (new_string, str); 511 new_string = concat2 (new_string, str);
510 } 512 }
511 513
@@ -5718,6 +5720,29 @@ make_scroll_bar_position (struct input_event *ev, Lisp_Object type)
5718 builtin_lisp_symbol (scroll_bar_parts[ev->part])); 5720 builtin_lisp_symbol (scroll_bar_parts[ev->part]));
5719} 5721}
5720 5722
5723#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
5724
5725/* Return whether or not the coordinates X and Y are inside the
5726 box of the menu-bar window of frame F. */
5727
5728static bool
5729coords_in_menu_bar_window (struct frame *f, int x, int y)
5730{
5731 struct window *window;
5732
5733 if (!WINDOWP (f->menu_bar_window))
5734 return false;
5735
5736 window = XWINDOW (f->menu_bar_window);
5737
5738 return (y >= WINDOW_TOP_EDGE_Y (window)
5739 && x >= WINDOW_LEFT_EDGE_X (window)
5740 && y <= WINDOW_BOTTOM_EDGE_Y (window)
5741 && x <= WINDOW_RIGHT_EDGE_X (window));
5742}
5743
5744#endif
5745
5721/* Given a struct input_event, build the lisp event which represents 5746/* Given a struct input_event, build the lisp event which represents
5722 it. If EVENT is 0, build a mouse movement event from the mouse 5747 it. If EVENT is 0, build a mouse movement event from the mouse
5723 movement buffer, which should have a movement event in it. 5748 movement buffer, which should have a movement event in it.
@@ -5970,10 +5995,32 @@ make_lispy_event (struct input_event *event)
5970 and ROW are set to frame relative glyph coordinates 5995 and ROW are set to frame relative glyph coordinates
5971 which are then used to determine whether this click is 5996 which are then used to determine whether this click is
5972 in a menu (non-toolkit version). */ 5997 in a menu (non-toolkit version). */
5973 if (!toolkit_menubar_in_use (f)) 5998 if (!toolkit_menubar_in_use (f)
5999#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
6000 /* Don't process events for menu bars if they are not
6001 in the menu bar window. */
6002 && (!FRAME_WINDOW_P (f)
6003 || coords_in_menu_bar_window (f, XFIXNUM (event->x),
6004 XFIXNUM (event->y)))
6005#endif
6006 )
5974 { 6007 {
5975 pixel_to_glyph_coords (f, XFIXNUM (event->x), XFIXNUM (event->y), 6008#if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
5976 &column, &row, NULL, 1); 6009 if (FRAME_WINDOW_P (f))
6010 {
6011 struct window *menu_w = XWINDOW (f->menu_bar_window);
6012 int x, y, dummy;
6013
6014 x = FRAME_TO_WINDOW_PIXEL_X (menu_w, XFIXNUM (event->x));
6015 y = FRAME_TO_WINDOW_PIXEL_Y (menu_w, XFIXNUM (event->y));
6016
6017 x_y_to_hpos_vpos (XWINDOW (f->menu_bar_window), x, y, &column, &row,
6018 NULL, NULL, &dummy);
6019 }
6020 else
6021#endif
6022 pixel_to_glyph_coords (f, XFIXNUM (event->x), XFIXNUM (event->y),
6023 &column, &row, NULL, 1);
5977 6024
5978 /* In the non-toolkit version, clicks on the menu bar 6025 /* In the non-toolkit version, clicks on the menu bar
5979 are ordinary button events in the event buffer. 6026 are ordinary button events in the event buffer.
@@ -5983,7 +6030,7 @@ make_lispy_event (struct input_event *event)
5983 menu bar and Emacs doesn't know about it until 6030 menu bar and Emacs doesn't know about it until
5984 after the user makes a selection.) */ 6031 after the user makes a selection.) */
5985 if (row >= 0 && row < FRAME_MENU_BAR_LINES (f) 6032 if (row >= 0 && row < FRAME_MENU_BAR_LINES (f)
5986 && (event->modifiers & down_modifier)) 6033 && (event->modifiers & down_modifier))
5987 { 6034 {
5988 Lisp_Object items, item; 6035 Lisp_Object items, item;
5989 6036
diff --git a/src/lisp.h b/src/lisp.h
index 64167856835..8a5b8dad831 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4690,7 +4690,7 @@ extern void syms_of_editfns (void);
4690extern bool mouse_face_overlay_overlaps (Lisp_Object); 4690extern bool mouse_face_overlay_overlaps (Lisp_Object);
4691extern Lisp_Object disable_line_numbers_overlay_at_eob (void); 4691extern Lisp_Object disable_line_numbers_overlay_at_eob (void);
4692extern AVOID nsberror (Lisp_Object); 4692extern AVOID nsberror (Lisp_Object);
4693extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t); 4693extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool);
4694extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); 4694extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t);
4695extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t); 4695extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t);
4696extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool, 4696extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool,
@@ -4915,6 +4915,7 @@ extern bool running_asynch_code;
4915 4915
4916/* Defined in process.c. */ 4916/* Defined in process.c. */
4917struct Lisp_Process; 4917struct Lisp_Process;
4918extern void child_signal_init (void);
4918extern void kill_buffer_processes (Lisp_Object); 4919extern void kill_buffer_processes (Lisp_Object);
4919extern int wait_reading_process_output (intmax_t, int, int, bool, Lisp_Object, 4920extern int wait_reading_process_output (intmax_t, int, int, bool, Lisp_Object,
4920 struct Lisp_Process *, int); 4921 struct Lisp_Process *, int);
diff --git a/src/lread.c b/src/lread.c
index dfa4d9afb51..2a57f721943 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1236,7 +1236,8 @@ Return t if the file exists and loads successfully. */)
1236 /* If file name is magic, call the handler. */ 1236 /* If file name is magic, call the handler. */
1237 handler = Ffind_file_name_handler (file, Qload); 1237 handler = Ffind_file_name_handler (file, Qload);
1238 if (!NILP (handler)) 1238 if (!NILP (handler))
1239 return call5 (handler, Qload, file, noerror, nomessage, nosuffix); 1239 return
1240 call6 (handler, Qload, file, noerror, nomessage, nosuffix, must_suffix);
1240 1241
1241 /* The presence of this call is the result of a historical accident: 1242 /* The presence of this call is the result of a historical accident:
1242 it used to be in every file-operation and when it got removed 1243 it used to be in every file-operation and when it got removed
@@ -1740,12 +1741,15 @@ maybe_swap_for_eln (bool no_native, Lisp_Object *filename, int *fd,
1740 Vload_path, 1741 Vload_path,
1741 Qnil, Qnil))) 1742 Qnil, Qnil)))
1742 return; 1743 return;
1743 call2 (intern_c_string ("display-warning"), 1744 Vdelayed_warnings_list
1744 Qcomp, 1745 = Fcons (list2
1745 CALLN (Fformat, 1746 (Qcomp,
1746 build_string ("Cannot look up eln file as " 1747 CALLN (Fformat,
1747 "no source file was found for %s"), 1748 build_string ("Cannot look up eln "
1748 *filename)); 1749 "file as no source file "
1750 "was found for %s"),
1751 *filename)),
1752 Vdelayed_warnings_list);
1749 return; 1753 return;
1750 } 1754 }
1751 } 1755 }
@@ -5619,7 +5623,8 @@ from the file, and matches them against this regular expression.
5619When the regular expression matches, the file is considered to be safe 5623When the regular expression matches, the file is considered to be safe
5620to load. */); 5624to load. */);
5621 Vbytecomp_version_regexp 5625 Vbytecomp_version_regexp
5622 = build_pure_c_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)"); 5626 = build_pure_c_string
5627 ("^;;;.\\(?:in Emacs version\\|bytecomp version FSF\\)");
5623 5628
5624 DEFSYM (Qlexical_binding, "lexical-binding"); 5629 DEFSYM (Qlexical_binding, "lexical-binding");
5625 DEFVAR_LISP ("lexical-binding", Vlexical_binding, 5630 DEFVAR_LISP ("lexical-binding", Vlexical_binding,
diff --git a/src/nsfns.m b/src/nsfns.m
index 2699cf37a5b..d793bcf13ff 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -632,10 +632,19 @@ ns_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
632void 632void
633ns_change_tab_bar_height (struct frame *f, int height) 633ns_change_tab_bar_height (struct frame *f, int height)
634{ 634{
635 int unit = FRAME_LINE_HEIGHT (f); 635 int unit, old_height, lines;
636 int old_height = FRAME_TAB_BAR_HEIGHT (f); 636 Lisp_Object fullscreen;
637 int lines = (height + unit - 1) / unit; 637
638 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); 638 unit = FRAME_LINE_HEIGHT (f);
639 old_height = FRAME_TAB_BAR_HEIGHT (f);
640 fullscreen = get_frame_param (f, Qfullscreen);
641
642 /* This differs from the tool bar code in that the tab bar height is
643 not rounded up. Otherwise, if redisplay_tab_bar decides to grow
644 the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
645 leading to the tab bar height being incorrectly set upon the next
646 call to x_set_font. (bug#59285) */
647 lines = height / unit;
639 648
640 /* Make sure we redisplay all windows in this frame. */ 649 /* Make sure we redisplay all windows in this frame. */
641 fset_redisplay (f); 650 fset_redisplay (f);
diff --git a/src/nsimage.m b/src/nsimage.m
index 9cb5090dd0d..dd8768664a4 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -74,8 +74,10 @@ ns_can_use_native_image_api (Lisp_Object type)
74 imageType = @"com.compuserve.gif"; 74 imageType = @"com.compuserve.gif";
75 else if (EQ (type, Qtiff)) 75 else if (EQ (type, Qtiff))
76 imageType = @"public.tiff"; 76 imageType = @"public.tiff";
77#ifndef HAVE_RSVG
77 else if (EQ (type, Qsvg)) 78 else if (EQ (type, Qsvg))
78 imageType = @"public.svg-image"; 79 imageType = @"public.svg-image";
80#endif
79 else if (EQ (type, Qheic)) 81 else if (EQ (type, Qheic))
80 imageType = @"public.heic"; 82 imageType = @"public.heic";
81 83
diff --git a/src/nsterm.m b/src/nsterm.m
index 17f40dc7e37..507f2a9e7da 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7056,6 +7056,36 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
7056 processingCompose = NO; 7056 processingCompose = NO;
7057} 7057}
7058 7058
7059static Lisp_Object
7060ns_in_echo_area_1 (void *ptr)
7061{
7062 Lisp_Object in_echo_area;
7063 specpdl_ref count;
7064
7065 count = SPECPDL_INDEX ();
7066 specbind (Qinhibit_quit, Qt);
7067 in_echo_area = safe_call (1, Qns_in_echo_area);
7068
7069 return unbind_to (count, in_echo_area);
7070}
7071
7072static Lisp_Object
7073ns_in_echo_area_2 (enum nonlocal_exit exit, Lisp_Object error)
7074{
7075 return Qnil;
7076}
7077
7078static bool
7079ns_in_echo_area (void)
7080{
7081 Lisp_Object in_echo_area;
7082
7083 in_echo_area
7084 = internal_catch_all (ns_in_echo_area_1, NULL,
7085 ns_in_echo_area_2);
7086
7087 return !NILP (in_echo_area);
7088}
7059 7089
7060/* Used to position char selection windows, etc. */ 7090/* Used to position char selection windows, etc. */
7061- (NSRect)firstRectForCharacterRange: (NSRange)theRange 7091- (NSRect)firstRectForCharacterRange: (NSRange)theRange
@@ -7069,7 +7099,7 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
7069 if (NS_KEYLOG) 7099 if (NS_KEYLOG)
7070 NSLog (@"firstRectForCharRange request"); 7100 NSLog (@"firstRectForCharRange request");
7071 7101
7072 if (WINDOWP (echo_area_window) && ! NILP (call0 (intern ("ns-in-echo-area")))) 7102 if (WINDOWP (echo_area_window) && ns_in_echo_area ())
7073 win = XWINDOW (echo_area_window); 7103 win = XWINDOW (echo_area_window);
7074 else 7104 else
7075 win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe)); 7105 win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
@@ -11012,6 +11042,7 @@ respectively. */);
11012 DEFSYM (Qcondensed, "condensed"); 11042 DEFSYM (Qcondensed, "condensed");
11013 DEFSYM (Qreverse_italic, "reverse-italic"); 11043 DEFSYM (Qreverse_italic, "reverse-italic");
11014 DEFSYM (Qexpanded, "expanded"); 11044 DEFSYM (Qexpanded, "expanded");
11045 DEFSYM (Qns_in_echo_area, "ns-in-echo-area");
11015 11046
11016#ifdef NS_IMPL_COCOA 11047#ifdef NS_IMPL_COCOA
11017 Fprovide (Qcocoa, Qnil); 11048 Fprovide (Qcocoa, Qnil);
diff --git a/src/pdumper.c b/src/pdumper.c
index d6ae57afb2e..0a5d96dbb7c 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2137,8 +2137,8 @@ static dump_off
2137dump_interval_node (struct dump_context *ctx, struct itree_node *node, 2137dump_interval_node (struct dump_context *ctx, struct itree_node *node,
2138 dump_off parent_offset) 2138 dump_off parent_offset)
2139{ 2139{
2140#if CHECK_STRUCTS && !defined (HASH_interval_node_5765524F7E) 2140#if CHECK_STRUCTS && !defined (HASH_itree_node_50DE304F13)
2141# error "interval_node changed. See CHECK_STRUCTS comment in config.h." 2141# error "itree_node changed. See CHECK_STRUCTS comment in config.h."
2142#endif 2142#endif
2143 struct itree_node out; 2143 struct itree_node out;
2144 dump_object_start (ctx, &out, sizeof (out)); 2144 dump_object_start (ctx, &out, sizeof (out));
@@ -2179,7 +2179,7 @@ dump_interval_node (struct dump_context *ctx, struct itree_node *node,
2179static dump_off 2179static dump_off
2180dump_overlay (struct dump_context *ctx, const struct Lisp_Overlay *overlay) 2180dump_overlay (struct dump_context *ctx, const struct Lisp_Overlay *overlay)
2181{ 2181{
2182#if CHECK_STRUCTS && !defined (HASH_Lisp_Overlay_1CD4249AEC) 2182#if CHECK_STRUCTS && !defined (HASH_Lisp_Overlay_EB4C05D8D2)
2183# error "Lisp_Overlay changed. See CHECK_STRUCTS comment in config.h." 2183# error "Lisp_Overlay changed. See CHECK_STRUCTS comment in config.h."
2184#endif 2184#endif
2185 START_DUMP_PVEC (ctx, &overlay->header, struct Lisp_Overlay, out); 2185 START_DUMP_PVEC (ctx, &overlay->header, struct Lisp_Overlay, out);
@@ -2748,7 +2748,7 @@ dump_hash_table (struct dump_context *ctx,
2748static dump_off 2748static dump_off
2749dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) 2749dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2750{ 2750{
2751#if CHECK_STRUCTS && !defined HASH_buffer_F0F08347A5 2751#if CHECK_STRUCTS && !defined HASH_buffer_193CAA5E45
2752# error "buffer changed. See CHECK_STRUCTS comment in config.h." 2752# error "buffer changed. See CHECK_STRUCTS comment in config.h."
2753#endif 2753#endif
2754 struct buffer munged_buffer = *in_buffer; 2754 struct buffer munged_buffer = *in_buffer;
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 9473e14f5cf..a32067af818 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -473,10 +473,19 @@ pgtk_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
473void 473void
474pgtk_change_tab_bar_height (struct frame *f, int height) 474pgtk_change_tab_bar_height (struct frame *f, int height)
475{ 475{
476 int unit = FRAME_LINE_HEIGHT (f); 476 int unit, old_height, lines;
477 int old_height = FRAME_TAB_BAR_HEIGHT (f); 477 Lisp_Object fullscreen;
478 int lines = (height + unit - 1) / unit; 478
479 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); 479 unit = FRAME_LINE_HEIGHT (f);
480 old_height = FRAME_TAB_BAR_HEIGHT (f);
481 fullscreen = get_frame_param (f, Qfullscreen);
482
483 /* This differs from the tool bar code in that the tab bar height is
484 not rounded up. Otherwise, if redisplay_tab_bar decides to grow
485 the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
486 leading to the tab bar height being incorrectly set upon the next
487 call to x_set_font. (bug#59285) */
488 lines = height / unit;
480 489
481 /* Make sure we redisplay all windows in this frame. */ 490 /* Make sure we redisplay all windows in this frame. */
482 fset_redisplay (f); 491 fset_redisplay (f);
@@ -1112,13 +1121,6 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms)
1112 if (NILP (font)) 1121 if (NILP (font))
1113 error ("No suitable font was found"); 1122 error ("No suitable font was found");
1114 } 1123 }
1115 else if (!NILP (font_param))
1116 {
1117 /* Remember the explicit font parameter, so we can re-apply it after
1118 we've applied the `default' face settings. */
1119 AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
1120 gui_set_frame_parameters (f, arg);
1121 }
1122 1124
1123 /* This call will make X resources override any system font setting. */ 1125 /* This call will make X resources override any system font setting. */
1124 gui_default_parameter (f, parms, Qfont, font, "font", "Font", 1126 gui_default_parameter (f, parms, Qfont, font, "font", "Font",
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 491ba338821..13f6c6c3c4d 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -511,16 +511,16 @@ pgtk_free_frame_resources (struct frame *f)
511 511
512 if (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider != NULL) 512 if (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider != NULL)
513 { 513 {
514 GtkCssProvider *old = 514 GtkCssProvider *old
515 FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider; 515 = FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider;
516 g_object_unref (old); 516 g_object_unref (old);
517 FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider = NULL; 517 FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider = NULL;
518 } 518 }
519 519
520 if (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider != NULL) 520 if (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider != NULL)
521 { 521 {
522 GtkCssProvider *old = 522 GtkCssProvider *old
523 FRAME_X_OUTPUT (f)->scrollbar_background_css_provider; 523 = FRAME_X_OUTPUT (f)->scrollbar_background_css_provider;
524 g_object_unref (old); 524 g_object_unref (old);
525 FRAME_X_OUTPUT (f)->scrollbar_background_css_provider = NULL; 525 FRAME_X_OUTPUT (f)->scrollbar_background_css_provider = NULL;
526 } 526 }
@@ -714,40 +714,42 @@ pgtk_set_window_size (struct frame *f, bool change_gravity,
714 714
715void 715void
716pgtk_iconify_frame (struct frame *f) 716pgtk_iconify_frame (struct frame *f)
717/* --------------------------------------------------------------------------
718 External: Iconify window
719 -------------------------------------------------------------------------- */
720{ 717{
718 GtkWindow *window;
719
721 /* Don't keep the highlight on an invisible frame. */ 720 /* Don't keep the highlight on an invisible frame. */
721
722 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f) 722 if (FRAME_DISPLAY_INFO (f)->highlight_frame == f)
723 FRAME_DISPLAY_INFO (f)->highlight_frame = 0; 723 FRAME_DISPLAY_INFO (f)->highlight_frame = NULL;
724
725 /* If the frame is already iconified, return. */
724 726
725 if (FRAME_ICONIFIED_P (f)) 727 if (FRAME_ICONIFIED_P (f))
726 return; 728 return;
727 729
728 block_input (); 730 /* Child frames on PGTK have no outer widgets. In that case, simply
731 refuse to iconify the frame. */
729 732
730 if (FRAME_GTK_OUTER_WIDGET (f)) 733 if (FRAME_GTK_OUTER_WIDGET (f))
731 { 734 {
732 if (!FRAME_VISIBLE_P (f)) 735 if (!FRAME_VISIBLE_P (f))
733 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); 736 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
734 737
735 gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); 738 window = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
736 SET_FRAME_VISIBLE (f, 0);
737 SET_FRAME_ICONIFIED (f, true);
738 unblock_input ();
739 return;
740 }
741 739
742 /* Make sure the X server knows where the window should be positioned, 740 gtk_window_iconify (window);
743 in case the user deiconifies with the window manager. */
744 if (!FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
745 pgtk_set_offset (f, f->left_pos, f->top_pos, 0);
746 741
747 SET_FRAME_ICONIFIED (f, true); 742 /* Don't make the frame iconified here. Doing so will cause it
748 SET_FRAME_VISIBLE (f, 0); 743 to be skipped by redisplay, until GDK says it is deiconified
744 (see window_state_event for more details). However, if the
745 window server rejects the iconification request, GDK will
746 never tell Emacs about the iconification not happening,
747 leading to the frame not being redisplayed until the next
748 window state change. */
749 749
750 unblock_input (); 750 /* SET_FRAME_VISIBLE (f, 0);
751 SET_FRAME_ICONIFIED (f, true); */
752 }
751} 753}
752 754
753static gboolean 755static gboolean
@@ -1331,8 +1333,8 @@ fill_background_by_face (struct frame *f, struct face *face, int x, int y,
1331 1333
1332 if (face->stipple != 0) 1334 if (face->stipple != 0)
1333 { 1335 {
1334 cairo_pattern_t *mask = 1336 cairo_pattern_t *mask
1335 FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].pattern; 1337 = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].pattern;
1336 1338
1337 double r = ((face->foreground >> 16) & 0xff) / 255.0; 1339 double r = ((face->foreground >> 16) & 0xff) / 255.0;
1338 double g = ((face->foreground >> 8) & 0xff) / 255.0; 1340 double g = ((face->foreground >> 8) & 0xff) / 255.0;
@@ -1604,8 +1606,8 @@ pgtk_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1604 1606
1605 /* It is assured that all LEN characters in STR is ASCII. */ 1607 /* It is assured that all LEN characters in STR is ASCII. */
1606 for (j = 0; j < len; j++) 1608 for (j = 0; j < len; j++)
1607 char2b[j] = 1609 char2b[j]
1608 s->font->driver->encode_char (s->font, str[j]) & 0xFFFF; 1610 = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF;
1609 s->font->driver->draw (s, 0, upper_len, 1611 s->font->driver->draw (s, 0, upper_len,
1610 x + glyph->slice.glyphless.upper_xoff, 1612 x + glyph->slice.glyphless.upper_xoff,
1611 s->ybase + glyph->slice.glyphless.upper_yoff, 1613 s->ybase + glyph->slice.glyphless.upper_yoff,
@@ -2956,8 +2958,8 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
2956 2958
2957 if (w == XWINDOW (f->selected_window)) 2959 if (w == XWINDOW (f->selected_window))
2958 { 2960 {
2959 int frame_x = 2961 int frame_x = (WINDOW_TO_FRAME_PIXEL_X (w, x)
2960 WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w); 2962 + WINDOW_LEFT_FRINGE_WIDTH (w));
2961 int frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, y); 2963 int frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2962 pgtk_im_set_cursor_location (f, frame_x, frame_y, 2964 pgtk_im_set_cursor_location (f, frame_x, frame_y,
2963 w->phys_cursor_width, 2965 w->phys_cursor_width,
@@ -4516,16 +4518,29 @@ pgtk_free_pixmap (struct frame *f, Emacs_Pixmap pixmap)
4516void 4518void
4517pgtk_focus_frame (struct frame *f, bool noactivate) 4519pgtk_focus_frame (struct frame *f, bool noactivate)
4518{ 4520{
4519 struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); 4521 struct pgtk_display_info *dpyinfo;
4522 GtkWidget *widget;
4523 GtkWindow *window;
4520 4524
4521 GtkWidget *wid = FRAME_WIDGET (f); 4525 dpyinfo = FRAME_DISPLAY_INFO (f);
4522 4526
4523 if (dpyinfo->x_focus_frame != f && wid != NULL) 4527 if (FRAME_GTK_OUTER_WIDGET (f) && !noactivate)
4524 { 4528 {
4525 block_input (); 4529 /* The user says it is okay to activate the frame. Call
4526 gtk_widget_grab_focus (wid); 4530 gtk_window_present_with_time. If the timestamp specified
4527 unblock_input (); 4531 (actually a display serial on Wayland) is new enough, then
4532 any Wayland compositor supporting gtk_surface1_present will
4533 cause the frame to be activated. */
4534
4535 window = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
4536 gtk_window_present_with_time (window, dpyinfo->last_user_time);
4537 return;
4528 } 4538 }
4539
4540 widget = FRAME_WIDGET (f);
4541
4542 if (widget)
4543 gtk_widget_grab_focus (widget);
4529} 4544}
4530 4545
4531static void 4546static void
@@ -5142,13 +5157,15 @@ static gboolean
5142key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) 5157key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
5143{ 5158{
5144 union buffered_input_event inev; 5159 union buffered_input_event inev;
5145 ptrdiff_t nbytes = 0; 5160 ptrdiff_t nbytes;
5146 Mouse_HLInfo *hlinfo; 5161 Mouse_HLInfo *hlinfo;
5147 struct frame *f; 5162 struct frame *f;
5163 struct pgtk_display_info *dpyinfo;
5148 5164
5149 f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); 5165 f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
5150 EVENT_INIT (inev.ie); 5166 EVENT_INIT (inev.ie);
5151 hlinfo = MOUSE_HL_INFO (f); 5167 hlinfo = MOUSE_HL_INFO (f);
5168 nbytes = 0;
5152 5169
5153 /* If mouse-highlight is an integer, input clears out 5170 /* If mouse-highlight is an integer, input clears out
5154 mouse highlighting. */ 5171 mouse highlighting. */
@@ -5179,6 +5196,12 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
5179 Lisp_Object c; 5196 Lisp_Object c;
5180 guint state; 5197 guint state;
5181 5198
5199 dpyinfo = FRAME_DISPLAY_INFO (f);
5200
5201 /* Set the last user time for pgtk_focus_frame to work
5202 correctly. */
5203 dpyinfo->last_user_time = event->key.time;
5204
5182 state = event->key.state; 5205 state = event->key.state;
5183 5206
5184 /* While super is pressed, the input method will always always 5207 /* While super is pressed, the input method will always always
@@ -5212,8 +5235,8 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
5212 5235
5213 /* Common for all keysym input events. */ 5236 /* Common for all keysym input events. */
5214 XSETFRAME (inev.ie.frame_or_window, f); 5237 XSETFRAME (inev.ie.frame_or_window, f);
5215 inev.ie.modifiers = 5238 inev.ie.modifiers
5216 pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers); 5239 = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
5217 inev.ie.timestamp = event->key.time; 5240 inev.ie.timestamp = event->key.time;
5218 5241
5219 /* First deal with keysyms which have defined 5242 /* First deal with keysyms which have defined
@@ -5361,11 +5384,37 @@ done:
5361 return TRUE; 5384 return TRUE;
5362} 5385}
5363 5386
5387static struct pgtk_display_info *
5388pgtk_display_info_for_display (GdkDisplay *dpy)
5389{
5390 struct pgtk_display_info *dpyinfo;
5391
5392 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
5393 {
5394 if (dpyinfo->display == dpy)
5395 return dpyinfo;
5396 }
5397
5398 return NULL;
5399}
5400
5364static gboolean 5401static gboolean
5365key_release_event (GtkWidget *widget, 5402key_release_event (GtkWidget *widget,
5366 GdkEvent *event, 5403 GdkEvent *event,
5367 gpointer *user_data) 5404 gpointer *user_data)
5368{ 5405{
5406 GdkDisplay *display;
5407 struct pgtk_display_info *dpyinfo;
5408
5409 display = gtk_widget_get_display (widget);
5410 dpyinfo = pgtk_display_info_for_display (display);
5411
5412 if (dpyinfo)
5413 /* This is needed on Wayland because of some brain dead
5414 compositors. Without them, we would not have to keep track of
5415 the serial of key release events. */
5416 dpyinfo->last_user_time = event->key.time;
5417
5369 return TRUE; 5418 return TRUE;
5370} 5419}
5371 5420
@@ -5420,9 +5469,7 @@ map_event (GtkWidget *widget,
5420 /* Check if fullscreen was specified before we where mapped the 5469 /* Check if fullscreen was specified before we where mapped the
5421 first time, i.e. from the command line. */ 5470 first time, i.e. from the command line. */
5422 if (!FRAME_X_OUTPUT (f)->has_been_visible) 5471 if (!FRAME_X_OUTPUT (f)->has_been_visible)
5423 { 5472 set_fullscreen_state (f);
5424 set_fullscreen_state (f);
5425 }
5426 5473
5427 if (!iconified) 5474 if (!iconified)
5428 { 5475 {
@@ -5465,24 +5512,6 @@ window_state_event (GtkWidget *widget,
5465 inev.ie.kind = NO_EVENT; 5512 inev.ie.kind = NO_EVENT;
5466 inev.ie.arg = Qnil; 5513 inev.ie.arg = Qnil;
5467 5514
5468 if (f)
5469 {
5470 if (new_state & GDK_WINDOW_STATE_FOCUSED)
5471 {
5472 if (FRAME_ICONIFIED_P (f))
5473 {
5474 /* Gnome shell does not iconify us when C-z is pressed.
5475 It hides the frame. So if our state says we aren't
5476 hidden anymore, treat it as deiconified. */
5477 SET_FRAME_VISIBLE (f, 1);
5478 SET_FRAME_ICONIFIED (f, false);
5479 FRAME_X_OUTPUT (f)->has_been_visible = true;
5480 inev.ie.kind = DEICONIFY_EVENT;
5481 XSETFRAME (inev.ie.frame_or_window, f);
5482 }
5483 }
5484 }
5485
5486 if (new_state & GDK_WINDOW_STATE_FULLSCREEN) 5515 if (new_state & GDK_WINDOW_STATE_FULLSCREEN)
5487 store_frame_param (f, Qfullscreen, Qfullboth); 5516 store_frame_param (f, Qfullscreen, Qfullboth);
5488 else if (new_state & GDK_WINDOW_STATE_MAXIMIZED) 5517 else if (new_state & GDK_WINDOW_STATE_MAXIMIZED)
@@ -5500,14 +5529,37 @@ window_state_event (GtkWidget *widget,
5500 else 5529 else
5501 store_frame_param (f, Qfullscreen, Qnil); 5530 store_frame_param (f, Qfullscreen, Qnil);
5502 5531
5532 /* The Wayland protocol provides no way for the client to know
5533 whether or not one of its toplevels has actually been
5534 deiconified. It only provides a request for clients to iconify a
5535 toplevel, without even the ability to determine whether or not
5536 the iconification request was rejected by the display server.
5537
5538 GDK computes the iconified state by sending a window state event
5539 containing only GDK_WINDOW_STATE_ICONIFIED immediately after
5540 gtk_window_iconify is called. That is error-prone if the request
5541 to iconify the frame was rejected by the display server, but is
5542 not the main problem here, as Wayland compositors only rarely
5543 reject such requests. GDK also assumes that it can clear the
5544 iconified state upon receiving the next toplevel configure event
5545 from the display server. Unfortunately, such events can be sent
5546 by Wayland compositors while the frame is iconified, and may also
5547 not be sent upon deiconification. So, no matter what Emacs does,
5548 the iconification state of a frame is likely to be wrong under
5549 one situation or another. */
5550
5503 if (new_state & GDK_WINDOW_STATE_ICONIFIED) 5551 if (new_state & GDK_WINDOW_STATE_ICONIFIED)
5504 SET_FRAME_ICONIFIED (f, true); 5552 {
5553 SET_FRAME_ICONIFIED (f, true);
5554 SET_FRAME_VISIBLE (f, false);
5555 }
5505 else 5556 else
5506 { 5557 {
5507 FRAME_X_OUTPUT (f)->has_been_visible = true; 5558 FRAME_X_OUTPUT (f)->has_been_visible = true;
5508 inev.ie.kind = DEICONIFY_EVENT; 5559 inev.ie.kind = DEICONIFY_EVENT;
5509 XSETFRAME (inev.ie.frame_or_window, f); 5560 XSETFRAME (inev.ie.frame_or_window, f);
5510 SET_FRAME_ICONIFIED (f, false); 5561 SET_FRAME_ICONIFIED (f, false);
5562 SET_FRAME_VISIBLE (f, true);
5511 } 5563 }
5512 5564
5513 if (new_state & GDK_WINDOW_STATE_STICKY) 5565 if (new_state & GDK_WINDOW_STATE_STICKY)
@@ -5899,9 +5951,10 @@ construct_mouse_click (struct input_event *result,
5899 result->kind = MOUSE_CLICK_EVENT; 5951 result->kind = MOUSE_CLICK_EVENT;
5900 result->code = event->button - 1; 5952 result->code = event->button - 1;
5901 result->timestamp = event->time; 5953 result->timestamp = event->time;
5902 result->modifiers = 5954 result->modifiers = (pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
5903 (pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->state) | 5955 event->state)
5904 (event->type == GDK_BUTTON_RELEASE ? up_modifier : down_modifier)); 5956 | (event->type == GDK_BUTTON_RELEASE
5957 ? up_modifier : down_modifier));
5905 5958
5906 XSETINT (result->x, event->x); 5959 XSETINT (result->x, event->x);
5907 XSETINT (result->y, event->y); 5960 XSETINT (result->y, event->y);
@@ -5966,6 +6019,10 @@ button_event (GtkWidget *widget, GdkEvent *event,
5966 } 6019 }
5967 } 6020 }
5968 6021
6022 /* Set the last user time, used to activate the frame in
6023 pgtk_focus_frame. */
6024 dpyinfo->last_user_time = event->button.time;
6025
5969 if (f) 6026 if (f)
5970 { 6027 {
5971 /* Is this in the tab-bar? */ 6028 /* Is this in the tab-bar? */
@@ -5984,10 +6041,7 @@ button_event (GtkWidget *widget, GdkEvent *event,
5984 (f, x, y, event->type == GDK_BUTTON_PRESS, 6041 (f, x, y, event->type == GDK_BUTTON_PRESS,
5985 pgtk_gtk_to_emacs_modifiers (dpyinfo, event->button.state)); 6042 pgtk_gtk_to_emacs_modifiers (dpyinfo, event->button.state));
5986 } 6043 }
5987 }
5988 6044
5989 if (f)
5990 {
5991 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p) 6045 if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
5992 { 6046 {
5993 if (ignore_next_mouse_click_timeout) 6047 if (ignore_next_mouse_click_timeout)
@@ -6055,8 +6109,8 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
6055 6109
6056 inev.ie.kind = NO_EVENT; 6110 inev.ie.kind = NO_EVENT;
6057 inev.ie.timestamp = event->scroll.time; 6111 inev.ie.timestamp = event->scroll.time;
6058 inev.ie.modifiers = 6112 inev.ie.modifiers
6059 pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state); 6113 = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state);
6060 XSETINT (inev.ie.x, event->scroll.x); 6114 XSETINT (inev.ie.x, event->scroll.x);
6061 XSETINT (inev.ie.y, event->scroll.y); 6115 XSETINT (inev.ie.y, event->scroll.y);
6062 XSETFRAME (inev.ie.frame_or_window, f); 6116 XSETFRAME (inev.ie.frame_or_window, f);
@@ -6594,6 +6648,44 @@ pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
6594 return FALSE; 6648 return FALSE;
6595} 6649}
6596 6650
6651/* Display a warning message if the PGTK port is being used under X;
6652 that is not supported. */
6653
6654static void
6655pgtk_display_x_warning (GdkDisplay *display)
6656{
6657 GtkWidget *dialog_widget, *label, *content_area;
6658 GtkDialog *dialog;
6659 GtkWindow *window;
6660 GdkScreen *screen;
6661
6662 /* Do this instead of GDK_IS_X11_DISPLAY because the GDK X header
6663 pulls in Xlib, which conflicts with definitions in pgtkgui.h. */
6664 if (strcmp (G_OBJECT_TYPE_NAME (display),
6665 "GdkX11Display"))
6666 return;
6667
6668 dialog_widget = gtk_dialog_new ();
6669 dialog = GTK_DIALOG (dialog_widget);
6670 window = GTK_WINDOW (dialog_widget);
6671 screen = gdk_display_get_default_screen (display);
6672 content_area = gtk_dialog_get_content_area (dialog);
6673
6674 gtk_window_set_title (window, "Warning");
6675 gtk_window_set_screen (window, screen);
6676
6677 label = gtk_label_new ("You are trying to run Emacs configured with"
6678 " the \"pure-GTK\" interface under the X Window"
6679 " System. That configuration is unsupported and"
6680 " will lead to sporadic crashes during transfer of"
6681 " large selection data. It will also lead to"
6682 " various problems with keyboard input.");
6683 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
6684 gtk_container_add (GTK_CONTAINER (content_area), label);
6685 gtk_widget_show (label);
6686 gtk_widget_show (dialog_widget);
6687}
6688
6597/* Open a connection to X display DISPLAY_NAME, and return 6689/* Open a connection to X display DISPLAY_NAME, and return
6598 the structure that describes the open display. 6690 the structure that describes the open display.
6599 If we cannot contact the display, return null. */ 6691 If we cannot contact the display, return null. */
@@ -6697,6 +6789,9 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name)
6697 return 0; 6789 return 0;
6698 } 6790 }
6699 6791
6792 /* If the PGTK port is being used under X, complain very loudly, as
6793 that isn't supported. */
6794 pgtk_display_x_warning (dpy);
6700 6795
6701 dpyinfo = xzalloc (sizeof *dpyinfo); 6796 dpyinfo = xzalloc (sizeof *dpyinfo);
6702 pgtk_initialize_display_info (dpyinfo); 6797 pgtk_initialize_display_info (dpyinfo);
@@ -6940,10 +7035,9 @@ pgtk_parse_color (struct frame *f, const char *color_name,
6940 color->red = rgba.red * 65535; 7035 color->red = rgba.red * 65535;
6941 color->green = rgba.green * 65535; 7036 color->green = rgba.green * 65535;
6942 color->blue = rgba.blue * 65535; 7037 color->blue = rgba.blue * 65535;
6943 color->pixel = 7038 color->pixel = ((color->red >> 8) << 16
6944 (color->red >> 8) << 16 | 7039 | (color->green >> 8) << 8
6945 (color->green >> 8) << 8 | 7040 | (color->blue >> 8) << 0);
6946 (color->blue >> 8) << 0;
6947 return 1; 7041 return 1;
6948 } 7042 }
6949 return 0; 7043 return 0;
@@ -7072,10 +7166,9 @@ If set to a non-float value, there will be no wait at all. */);
7072 Vpgtk_wait_for_event_timeout = make_float (0.1); 7166 Vpgtk_wait_for_event_timeout = make_float (0.1);
7073 7167
7074 DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table, 7168 DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table,
7075 doc: /* Hash table of character codes indexed by X keysym codes. */); 7169 doc: /* Hash table of character codes indexed by X keysym codes. */);
7076 Vpgtk_keysym_table = 7170 Vpgtk_keysym_table = make_hash_table (hashtest_eql, 900, DEFAULT_REHASH_SIZE,
7077 make_hash_table (hashtest_eql, 900, DEFAULT_REHASH_SIZE, 7171 DEFAULT_REHASH_THRESHOLD, Qnil, false);
7078 DEFAULT_REHASH_THRESHOLD, Qnil, false);
7079 7172
7080 window_being_scrolled = Qnil; 7173 window_being_scrolled = Qnil;
7081 staticpro (&window_being_scrolled); 7174 staticpro (&window_being_scrolled);
@@ -7113,13 +7206,13 @@ pgtk_begin_cr_clip (struct frame *f)
7113 7206
7114 if (!cr) 7207 if (!cr)
7115 { 7208 {
7116 cairo_surface_t *surface = 7209 cairo_surface_t *surface
7117 gdk_window_create_similar_surface (gtk_widget_get_window 7210 = gdk_window_create_similar_surface (gtk_widget_get_window
7118 (FRAME_GTK_WIDGET (f)), 7211 (FRAME_GTK_WIDGET (f)),
7119 CAIRO_CONTENT_COLOR_ALPHA, 7212 CAIRO_CONTENT_COLOR_ALPHA,
7120 FRAME_CR_SURFACE_DESIRED_WIDTH (f), 7213 FRAME_CR_SURFACE_DESIRED_WIDTH (f),
7121 FRAME_CR_SURFACE_DESIRED_HEIGHT 7214 FRAME_CR_SURFACE_DESIRED_HEIGHT
7122 (f)); 7215 (f));
7123 7216
7124 cr = FRAME_CR_CONTEXT (f) = cairo_create (surface); 7217 cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
7125 cairo_surface_destroy (surface); 7218 cairo_surface_destroy (surface);
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index fcc6c5310e9..b6bd10dcb41 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -262,6 +262,13 @@ struct pgtk_output
262 unsigned long background_color; 262 unsigned long background_color;
263 void *toolbar; 263 void *toolbar;
264 264
265 /* The "time" of the last user interaction on this display. Set
266 upon button and key press and release events.
267
268 Under the GDK Wayland backend, this is actually an event
269 serial. */
270 guint32 last_user_time;
271
265 /* Cursors */ 272 /* Cursors */
266 Emacs_Cursor current_cursor; 273 Emacs_Cursor current_cursor;
267 Emacs_Cursor text_cursor; 274 Emacs_Cursor text_cursor;
@@ -357,8 +364,8 @@ struct pgtk_output
357 /* The tool bar in this frame */ 364 /* The tool bar in this frame */
358 GtkWidget *toolbar_widget; 365 GtkWidget *toolbar_widget;
359 /* True if tool bar is packed into the hbox widget (i.e. vertical). */ 366 /* True if tool bar is packed into the hbox widget (i.e. vertical). */
360 bool_bf toolbar_in_hbox:1; 367 bool_bf toolbar_in_hbox : 1;
361 bool_bf toolbar_is_packed:1; 368 bool_bf toolbar_is_packed : 1;
362 369
363 GtkTooltip *ttip_widget; 370 GtkTooltip *ttip_widget;
364 GtkWidget *ttip_lbl; 371 GtkWidget *ttip_lbl;
diff --git a/src/print.c b/src/print.c
index 65218084a4c..07560518c46 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2017,8 +2017,8 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
2017 i = sprintf (buf, " stmt=%p", XSQLITE (obj)->stmt); 2017 i = sprintf (buf, " stmt=%p", XSQLITE (obj)->stmt);
2018 strout (buf, i, i, printcharfun); 2018 strout (buf, i, i, printcharfun);
2019 } 2019 }
2020 i = sprintf (buf, " name=%s", XSQLITE (obj)->name); 2020 print_c_string (" name=", printcharfun);
2021 strout (buf, i, i, printcharfun); 2021 print_c_string (XSQLITE (obj)->name, printcharfun);
2022 printchar ('>', printcharfun); 2022 printchar ('>', printcharfun);
2023 } 2023 }
2024 break; 2024 break;
diff --git a/src/process.c b/src/process.c
index 358899cdede..5144c5d6c92 100644
--- a/src/process.c
+++ b/src/process.c
@@ -292,7 +292,6 @@ static int child_signal_read_fd = -1;
292 descriptor to notify `wait_reading_process_output' of process 292 descriptor to notify `wait_reading_process_output' of process
293 status changes. */ 293 status changes. */
294static int child_signal_write_fd = -1; 294static int child_signal_write_fd = -1;
295static void child_signal_init (void);
296#ifndef WINDOWSNT 295#ifndef WINDOWSNT
297static void child_signal_read (int, void *); 296static void child_signal_read (int, void *);
298#endif 297#endif
@@ -7323,7 +7322,7 @@ process has been transmitted to the serial port. */)
7323 7322
7324/* Set up `child_signal_read_fd' and `child_signal_write_fd'. */ 7323/* Set up `child_signal_read_fd' and `child_signal_write_fd'. */
7325 7324
7326static void 7325void
7327child_signal_init (void) 7326child_signal_init (void)
7328{ 7327{
7329 /* Either both are initialized, or both are uninitialized. */ 7328 /* Either both are initialized, or both are uninitialized. */
diff --git a/src/search.c b/src/search.c
index b5d6a442c0f..1c5831b6de7 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1558,7 +1558,6 @@ simple_search (EMACS_INT n, unsigned char *pat,
1558 while (1) 1558 while (1)
1559 { 1559 {
1560 /* Try matching at position POS. */ 1560 /* Try matching at position POS. */
1561 ptrdiff_t this_pos = pos;
1562 ptrdiff_t this_pos_byte = pos_byte; 1561 ptrdiff_t this_pos_byte = pos_byte;
1563 ptrdiff_t this_len = len; 1562 ptrdiff_t this_len = len;
1564 unsigned char *p = pat; 1563 unsigned char *p = pat;
@@ -1580,7 +1579,6 @@ simple_search (EMACS_INT n, unsigned char *pat,
1580 p += charlen; 1579 p += charlen;
1581 1580
1582 this_pos_byte += buf_charlen; 1581 this_pos_byte += buf_charlen;
1583 this_pos++;
1584 } 1582 }
1585 1583
1586 if (this_len == 0) 1584 if (this_len == 0)
@@ -2824,11 +2822,21 @@ Return value is undefined if the last search failed. */)
2824} 2822}
2825 2823
2826DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 3, 0, 2824DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 3, 0,
2827 doc: /* Return a list describing what the last search matched. 2825 doc: /* Return a list of positions that record text matched by the last search.
2828Element 2N is `(match-beginning N)'; element 2N + 1 is `(match-end N)'. 2826Element 2N of the returned list is the position of the beginning of the
2829All the elements are markers or nil (nil if the Nth pair didn't match) 2827match of the Nth subexpression; it corresponds to `(match-beginning N)';
2830if the last match was on a buffer; integers or nil if a string was matched. 2828element 2N + 1 is the position of the end of the match of the Nth
2831Use `set-match-data' to reinstate the data in this list. 2829subexpression; it corresponds to `(match-end N)'. See `match-beginning'
2830and `match-end'.
2831If the last search was on a buffer, all the elements are by default
2832markers or nil (nil when the Nth pair didn't match); they are integers
2833or nil if the search was on a string. But if the optional argument
2834INTEGERS is non-nil, the elements that represent buffer positions are
2835always integers, not markers, and (if the search was on a buffer) the
2836buffer itself is appended to the list as one additional element.
2837
2838Use `set-match-data' to reinstate the match data from the elements of
2839this list.
2832 2840
2833Note that non-matching optional groups at the end of the regexp are 2841Note that non-matching optional groups at the end of the regexp are
2834elided instead of being represented with two `nil's each. For instance: 2842elided instead of being represented with two `nil's each. For instance:
@@ -2838,16 +2846,13 @@ elided instead of being represented with two `nil's each. For instance:
2838 (match-data)) 2846 (match-data))
2839 => (0 1 nil nil 0 1) 2847 => (0 1 nil nil 0 1)
2840 2848
2841If INTEGERS (the optional first argument) is non-nil, always use 2849If REUSE is a list, store the value in REUSE by destructively modifying it.
2842integers (rather than markers) to represent buffer positions. In 2850If REUSE is long enough to hold all the values, its length remains the
2843this case, and if the last match was in a buffer, the buffer will get 2851same, and any unused elements are set to nil. If REUSE is not long
2844stored as one additional element at the end of the list. 2852enough, it is extended. Note that if REUSE is long enough and INTEGERS
2845 2853is non-nil, no consing is done to make the return value; this minimizes GC.
2846If REUSE is a list, reuse it as part of the value. If REUSE is long
2847enough to hold all the values, and if INTEGERS is non-nil, no consing
2848is done.
2849 2854
2850If optional third arg RESEAT is non-nil, any previous markers on the 2855If optional third argument RESEAT is non-nil, any previous markers on the
2851REUSE list will be modified to point to nowhere. 2856REUSE list will be modified to point to nowhere.
2852 2857
2853Return value is undefined if the last search failed. */) 2858Return value is undefined if the last search failed. */)
diff --git a/src/sqlite.c b/src/sqlite.c
index 08bf696b8ca..ac860f55bcd 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -52,7 +52,9 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_bind_null, (sqlite3_stmt*, int));
52DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); 52DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int));
53DEF_DLL_FN (SQLITE_API int, sqlite3_extended_errcode, (sqlite3*)); 53DEF_DLL_FN (SQLITE_API int, sqlite3_extended_errcode, (sqlite3*));
54DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); 54DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*));
55#if SQLITE_VERSION_NUMBER >= 3007015
55DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); 56DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int));
57#endif
56DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); 58DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*));
57DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); 59DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*));
58DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); 60DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*));
@@ -91,7 +93,9 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension,
91# undef sqlite3_bind_int 93# undef sqlite3_bind_int
92# undef sqlite3_extended_errcode 94# undef sqlite3_extended_errcode
93# undef sqlite3_errmsg 95# undef sqlite3_errmsg
94# undef sqlite3_errstr 96# if SQLITE_VERSION_NUMBER >= 3007015
97# undef sqlite3_errstr
98# endif
95# undef sqlite3_step 99# undef sqlite3_step
96# undef sqlite3_changes 100# undef sqlite3_changes
97# undef sqlite3_column_count 101# undef sqlite3_column_count
@@ -117,7 +121,9 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension,
117# define sqlite3_bind_int fn_sqlite3_bind_int 121# define sqlite3_bind_int fn_sqlite3_bind_int
118# define sqlite3_extended_errcode fn_sqlite3_extended_errcode 122# define sqlite3_extended_errcode fn_sqlite3_extended_errcode
119# define sqlite3_errmsg fn_sqlite3_errmsg 123# define sqlite3_errmsg fn_sqlite3_errmsg
120# define sqlite3_errstr fn_sqlite3_errstr 124# if SQLITE_VERSION_NUMBER >= 3007015
125# define sqlite3_errstr fn_sqlite3_errstr
126# endif
121# define sqlite3_step fn_sqlite3_step 127# define sqlite3_step fn_sqlite3_step
122# define sqlite3_changes fn_sqlite3_changes 128# define sqlite3_changes fn_sqlite3_changes
123# define sqlite3_column_count fn_sqlite3_column_count 129# define sqlite3_column_count fn_sqlite3_column_count
@@ -146,7 +152,9 @@ load_dll_functions (HMODULE library)
146 LOAD_DLL_FN (library, sqlite3_bind_int); 152 LOAD_DLL_FN (library, sqlite3_bind_int);
147 LOAD_DLL_FN (library, sqlite3_extended_errcode); 153 LOAD_DLL_FN (library, sqlite3_extended_errcode);
148 LOAD_DLL_FN (library, sqlite3_errmsg); 154 LOAD_DLL_FN (library, sqlite3_errmsg);
155#if SQLITE_VERSION_NUMBER >= 3007015
149 LOAD_DLL_FN (library, sqlite3_errstr); 156 LOAD_DLL_FN (library, sqlite3_errstr);
157#endif
150 LOAD_DLL_FN (library, sqlite3_step); 158 LOAD_DLL_FN (library, sqlite3_step);
151 LOAD_DLL_FN (library, sqlite3_changes); 159 LOAD_DLL_FN (library, sqlite3_changes);
152 LOAD_DLL_FN (library, sqlite3_column_count); 160 LOAD_DLL_FN (library, sqlite3_column_count);
@@ -428,13 +436,27 @@ row_to_value (sqlite3_stmt *stmt)
428static Lisp_Object 436static Lisp_Object
429sqlite_prepare_errdata (int code, sqlite3 *sdb) 437sqlite_prepare_errdata (int code, sqlite3 *sdb)
430{ 438{
431 Lisp_Object errstr = build_string (sqlite3_errstr (code));
432 Lisp_Object errcode = make_fixnum (code); 439 Lisp_Object errcode = make_fixnum (code);
433 /* More details about what went wrong. */
434 Lisp_Object ext_errcode = make_fixnum (sqlite3_extended_errcode (sdb));
435 const char *errmsg = sqlite3_errmsg (sdb); 440 const char *errmsg = sqlite3_errmsg (sdb);
436 return list4 (errstr, errmsg ? build_string (errmsg) : Qnil, 441 Lisp_Object lerrmsg = errmsg ? build_string (errmsg) : Qnil;
437 errcode, ext_errcode); 442 Lisp_Object errstr, ext_errcode;
443
444#if SQLITE_VERSION_NUMBER >= 3007015
445 errstr = build_string (sqlite3_errstr (code));
446#else
447 /* The internet says this is identical to sqlite3_errstr (code). */
448 errstr = lerrmsg;
449#endif
450
451 /* More details about what went wrong. */
452#if SQLITE_VERSION_NUMBER >= 3006005
453 ext_errcode = make_fixnum (sqlite3_extended_errcode (sdb));
454#else
455 /* What value to use here? */
456 ext_errcode = make_fixnum (0);
457#endif
458
459 return list4 (errstr, lerrmsg, errcode, ext_errcode);
438} 460}
439 461
440DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, 462DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0,
diff --git a/src/w32fns.c b/src/w32fns.c
index 93b7f80f268..887e5a1f7b7 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -1717,10 +1717,19 @@ w32_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1717void 1717void
1718w32_change_tab_bar_height (struct frame *f, int height) 1718w32_change_tab_bar_height (struct frame *f, int height)
1719{ 1719{
1720 int unit = FRAME_LINE_HEIGHT (f); 1720 int unit, old_height, lines;
1721 int old_height = FRAME_TAB_BAR_HEIGHT (f); 1721 Lisp_Object fullscreen;
1722 int lines = (height + unit - 1) / unit; 1722
1723 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); 1723 unit = FRAME_LINE_HEIGHT (f);
1724 old_height = FRAME_TAB_BAR_HEIGHT (f);
1725 fullscreen = get_frame_param (f, Qfullscreen);
1726
1727 /* This differs from the tool bar code in that the tab bar height is
1728 not rounded up. Otherwise, if redisplay_tab_bar decides to grow
1729 the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
1730 leading to the tab bar height being incorrectly set upon the next
1731 call to x_set_font. (bug#59285) */
1732 lines = height / unit;
1724 1733
1725 /* Make sure we redisplay all windows in this frame. */ 1734 /* Make sure we redisplay all windows in this frame. */
1726 fset_redisplay (f); 1735 fset_redisplay (f);
@@ -5785,13 +5794,7 @@ w32_default_font_parameter (struct frame *f, Lisp_Object parms)
5785 if (NILP (font)) 5794 if (NILP (font))
5786 error ("No suitable font was found"); 5795 error ("No suitable font was found");
5787 } 5796 }
5788 else if (!NILP (font_param)) 5797
5789 {
5790 /* Remember the explicit font parameter, so we can re-apply it after
5791 we've applied the `default' face settings. */
5792 gui_set_frame_parameters (f, Fcons (Fcons (Qfont_parameter, font_param),
5793 Qnil));
5794 }
5795 gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING); 5798 gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
5796} 5799}
5797 5800
@@ -8417,7 +8420,7 @@ a ShowWindow flag:
8417 8420
8418 current_dir = ENCODE_FILE (current_dir); 8421 current_dir = ENCODE_FILE (current_dir);
8419 /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could 8422 /* Cannot use filename_to_utf16/ansi with DOCUMENT, since it could
8420 be a URL that is not limited to MAX_PATH chararcters. */ 8423 be a URL that is not limited to MAX_PATH characters. */
8421 doclen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, 8424 doclen = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
8422 SSDATA (document), -1, NULL, 0); 8425 SSDATA (document), -1, NULL, 0);
8423 doc_w = xmalloc (doclen * sizeof (wchar_t)); 8426 doc_w = xmalloc (doclen * sizeof (wchar_t));
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 6a1d9afacf7..d13b0521c9a 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -648,7 +648,7 @@ handle_file_notifications (struct input_event *hold_quit)
648 ns = NULL; 648 ns = NULL;
649 649
650 /* Find out if there is a record available in the linked list of 650 /* Find out if there is a record available in the linked list of
651 notifications sets. If so, unlink te set from the linked list. 651 notifications sets. If so, unlink the set from the linked list.
652 Use the critical section. */ 652 Use the critical section. */
653 enter_crit (); 653 enter_crit ();
654 if (notifications_set_head->next != notifications_set_head) 654 if (notifications_set_head->next != notifications_set_head)
diff --git a/src/xdisp.c b/src/xdisp.c
index 3b330f315bc..fa5ce84b1c4 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2330,7 +2330,7 @@ pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2330 text, or we can't tell because W's current matrix is not up to 2330 text, or we can't tell because W's current matrix is not up to
2331 date. */ 2331 date. */
2332 2332
2333static struct glyph * 2333struct glyph *
2334x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos, 2334x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2335 int *dx, int *dy, int *area) 2335 int *dx, int *dy, int *area)
2336{ 2336{
@@ -3342,7 +3342,8 @@ init_iterator (struct it *it, struct window *w,
3342 { 3342 {
3343 /* Mode lines, menu bar in terminal frames. */ 3343 /* Mode lines, menu bar in terminal frames. */
3344 it->first_visible_x = 0; 3344 it->first_visible_x = 0;
3345 it->last_visible_x = body_width = WINDOW_PIXEL_WIDTH (w); 3345 it->last_visible_x =
3346 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3346 } 3347 }
3347 else 3348 else
3348 { 3349 {
@@ -3410,8 +3411,13 @@ init_iterator (struct it *it, struct window *w,
3410 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id); 3411 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3411 if (face && face->box != FACE_NO_BOX) 3412 if (face && face->box != FACE_NO_BOX)
3412 { 3413 {
3414 int box_thickness = face->box_vertical_line_width;
3413 it->face_box_p = true; 3415 it->face_box_p = true;
3414 it->start_of_box_run_p = true; 3416 it->start_of_box_run_p = true;
3417 /* Make sure we will have enough horizontal space to add the
3418 right box line at the end. */
3419 if (box_thickness > 0)
3420 it->last_visible_x -= box_thickness;
3415 } 3421 }
3416 } 3422 }
3417 3423
@@ -5324,6 +5330,8 @@ display_min_width (struct it *it, ptrdiff_t bufpos,
5324 /* Insert the stretch glyph. */ 5330 /* Insert the stretch glyph. */
5325 it->object = list3 (Qspace, QCwidth, w); 5331 it->object = list3 (Qspace, QCwidth, w);
5326 produce_stretch_glyph (it); 5332 produce_stretch_glyph (it);
5333 if (it->area == TEXT_AREA)
5334 it->current_x += it->pixel_width;
5327 it->min_width_property = Qnil; 5335 it->min_width_property = Qnil;
5328 } 5336 }
5329 } 5337 }
@@ -7036,17 +7044,11 @@ strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7036 str = Foverlay_get (overlay, Qbefore_string); 7044 str = Foverlay_get (overlay, Qbefore_string);
7037 if (STRINGP (str) && SCHARS (str) 7045 if (STRINGP (str) && SCHARS (str)
7038 && memchr (SDATA (str), '\n', SBYTES (str))) 7046 && memchr (SDATA (str), '\n', SBYTES (str)))
7039 { 7047 return true;
7040 ITREE_FOREACH_ABORT ();
7041 return true;
7042 }
7043 str = Foverlay_get (overlay, Qafter_string); 7048 str = Foverlay_get (overlay, Qafter_string);
7044 if (STRINGP (str) && SCHARS (str) 7049 if (STRINGP (str) && SCHARS (str)
7045 && memchr (SDATA (str), '\n', SBYTES (str))) 7050 && memchr (SDATA (str), '\n', SBYTES (str)))
7046 { 7051 return true;
7047 ITREE_FOREACH_ABORT ();
7048 return true;
7049 }
7050 } 7052 }
7051 7053
7052 /* Check for 'display' properties whose values include strings. */ 7054 /* Check for 'display' properties whose values include strings. */
@@ -23188,10 +23190,18 @@ extend_face_to_end_of_line (struct it *it)
23188 this is called when redisplaying a non-selected window, with 23190 this is called when redisplaying a non-selected window, with
23189 point temporarily moved to window-point. */ 23191 point temporarily moved to window-point. */
23190 specbind (Qinhibit_quit, Qt); 23192 specbind (Qinhibit_quit, Qt);
23191 const int extend_face_id = (it->face_id == DEFAULT_FACE_ID 23193 /* The default face, possibly remapped. */
23192 || it->s != NULL) 23194 struct face *default_face =
23193 ? DEFAULT_FACE_ID 23195 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23194 : face_at_pos (it, LFACE_EXTEND_INDEX); 23196 if (!default_face)
23197 return;
23198
23199 const int extend_face_id =
23200 (it->face_id == default_face->id || it->s != NULL)
23201 ? it->face_id
23202 : (it->glyph_row->ends_at_zv_p
23203 ? default_face->id
23204 : face_at_pos (it, LFACE_EXTEND_INDEX));
23195 unbind_to (count, Qnil); 23205 unbind_to (count, Qnil);
23196 23206
23197 /* Face extension extends the background and box of IT->extend_face_id 23207 /* Face extension extends the background and box of IT->extend_face_id
@@ -23228,14 +23238,8 @@ extend_face_to_end_of_line (struct it *it)
23228 if (!ASCII_CHAR_P (it->c)) 23238 if (!ASCII_CHAR_P (it->c))
23229 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil); 23239 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23230 23240
23231 /* The default face, possibly remapped. */
23232 struct face *default_face =
23233 FACE_FROM_ID (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23234 23241
23235#ifdef HAVE_WINDOW_SYSTEM 23242#ifdef HAVE_WINDOW_SYSTEM
23236 if (default_face == NULL)
23237 error ("extend_face_to_end_of_line: default_face is not set!");
23238
23239 if (FRAME_WINDOW_P (f)) 23243 if (FRAME_WINDOW_P (f))
23240 { 23244 {
23241 /* If the row is empty, add a space with the current face of IT, 23245 /* If the row is empty, add a space with the current face of IT,
@@ -26751,7 +26755,17 @@ display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
26751 { 26755 {
26752 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA] 26756 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26753 + it.glyph_row->used[TEXT_AREA] - 1); 26757 + it.glyph_row->used[TEXT_AREA] - 1);
26758 int box_thickness = face->box_vertical_line_width;
26754 last->right_box_line_p = true; 26759 last->right_box_line_p = true;
26760 /* Add back the space for the right box line we subtracted in
26761 init_iterator, since the right_box_line_p flag will make the
26762 glyph wider. We actually add only as much space as is
26763 available for the last glyph of the modeline and whatever
26764 space is left beyond it, since that glyph could be only
26765 partially visible */
26766 if (box_thickness > 0)
26767 last->pixel_width += max (0, (box_thickness
26768 - (it.current_x - it.last_visible_x)));
26755 } 26769 }
26756 26770
26757 return it.glyph_row->height; 26771 return it.glyph_row->height;
@@ -33597,8 +33611,14 @@ coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
33597bool 33611bool
33598cursor_in_mouse_face_p (struct window *w) 33612cursor_in_mouse_face_p (struct window *w)
33599{ 33613{
33600 int hpos = w->phys_cursor.hpos;
33601 int vpos = w->phys_cursor.vpos; 33614 int vpos = w->phys_cursor.vpos;
33615
33616 /* If the cursor is outside the matrix glyph rows, it cannot be
33617 within the mouse face. */
33618 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
33619 return false;
33620
33621 int hpos = w->phys_cursor.hpos;
33602 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos); 33622 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
33603 33623
33604 /* When the window is hscrolled, cursor hpos can legitimately be out 33624 /* When the window is hscrolled, cursor hpos can legitimately be out
diff --git a/src/xfaces.c b/src/xfaces.c
index ed76db9adb7..df078227c8a 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -3809,8 +3809,12 @@ set_font_frame_param (Lisp_Object frame, Lisp_Object lface)
3809 ASET (lface, LFACE_FONT_INDEX, font); 3809 ASET (lface, LFACE_FONT_INDEX, font);
3810 } 3810 }
3811 f->default_face_done_p = false; 3811 f->default_face_done_p = false;
3812 AUTO_FRAME_ARG (arg, Qfont, font); 3812 AUTO_LIST2 (arg, AUTO_CONS_EXPR (Qfont, font),
3813 Fmodify_frame_parameters (frame, arg); 3813 /* Clear the `font-parameter' frame property, as the
3814 font is now being specified by a face, not a
3815 frame property. */
3816 AUTO_CONS_EXPR (Qfont_parameter, Qnil));
3817 gui_set_frame_parameters_1 (f, arg, true);
3814 } 3818 }
3815} 3819}
3816 3820
@@ -4208,7 +4212,17 @@ Default face attributes override any local face attributes. */)
4208 { 4212 {
4209 Lisp_Object name = newface->font->props[FONT_NAME_INDEX]; 4213 Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
4210 AUTO_FRAME_ARG (arg, Qfont, name); 4214 AUTO_FRAME_ARG (arg, Qfont, name);
4211 Fmodify_frame_parameters (frame, arg); 4215
4216#ifdef HAVE_WINDOW_SYSTEM
4217 if (FRAME_WINDOW_P (f))
4218 /* This is a window-system frame. Prevent changes of
4219 the `font' parameter here from messing with the
4220 `font-parameter' frame property, as the frame
4221 parameter is not being changed by the user. */
4222 gui_set_frame_parameters_1 (f, arg, true);
4223 else
4224#endif
4225 Fmodify_frame_parameters (frame, arg);
4212 } 4226 }
4213 4227
4214 if (STRINGP (gvec[LFACE_FOREGROUND_INDEX])) 4228 if (STRINGP (gvec[LFACE_FOREGROUND_INDEX]))
diff --git a/src/xfns.c b/src/xfns.c
index 3ff7a8c2865..95092ce05f4 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1362,13 +1362,21 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1362 char *xmessage = alloca (1 + message_length); 1362 char *xmessage = alloca (1 + message_length);
1363 memcpy (xmessage, cursor_data.error_string, message_length); 1363 memcpy (xmessage, cursor_data.error_string, message_length);
1364 1364
1365 x_uncatch_errors (); 1365 x_uncatch_errors_after_check ();
1366
1367 /* XFreeCursor can generate BadCursor errors, because
1368 XCreateFontCursor is not a request that waits for a reply,
1369 and as such can return IDs that will not actually be used by
1370 the server. */
1371 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
1366 1372
1367 /* Free any successfully created cursors. */ 1373 /* Free any successfully created cursors. */
1368 for (i = 0; i < mouse_cursor_max; i++) 1374 for (i = 0; i < mouse_cursor_max; i++)
1369 if (cursor_data.cursor[i] != 0) 1375 if (cursor_data.cursor[i] != 0)
1370 XFreeCursor (dpy, cursor_data.cursor[i]); 1376 XFreeCursor (dpy, cursor_data.cursor[i]);
1371 1377
1378 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
1379
1372 /* This should only be able to fail if the server's serial 1380 /* This should only be able to fail if the server's serial
1373 number tracking is broken. */ 1381 number tracking is broken. */
1374 if (cursor_data.error_cursor >= 0) 1382 if (cursor_data.error_cursor >= 0)
@@ -1750,10 +1758,19 @@ x_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1750void 1758void
1751x_change_tab_bar_height (struct frame *f, int height) 1759x_change_tab_bar_height (struct frame *f, int height)
1752{ 1760{
1753 int unit = FRAME_LINE_HEIGHT (f); 1761 int unit, old_height, lines;
1754 int old_height = FRAME_TAB_BAR_HEIGHT (f); 1762 Lisp_Object fullscreen;
1755 int lines = (height + unit - 1) / unit; 1763
1756 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); 1764 unit = FRAME_LINE_HEIGHT (f);
1765 old_height = FRAME_TAB_BAR_HEIGHT (f);
1766 fullscreen = get_frame_param (f, Qfullscreen);
1767
1768 /* This differs from the tool bar code in that the tab bar height is
1769 not rounded up. Otherwise, if redisplay_tab_bar decides to grow
1770 the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
1771 leading to the tab bar height being incorrectly set upon the next
1772 call to x_set_font. (bug#59285) */
1773 lines = height / unit;
1757 1774
1758 /* Make sure we redisplay all windows in this frame. */ 1775 /* Make sure we redisplay all windows in this frame. */
1759 fset_redisplay (f); 1776 fset_redisplay (f);
@@ -4506,9 +4523,11 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
4506 } 4523 }
4507 4524
4508 if (NILP (font)) 4525 if (NILP (font))
4509 font = !NILP (font_param) ? font_param 4526 font = (!NILP (font_param)
4510 : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", 4527 ? font_param
4511 RES_TYPE_STRING); 4528 : gui_display_get_arg (dpyinfo, parms,
4529 Qfont, "font", "Font",
4530 RES_TYPE_STRING));
4512 4531
4513 if (! FONTP (font) && ! STRINGP (font)) 4532 if (! FONTP (font) && ! STRINGP (font))
4514 { 4533 {
@@ -4540,13 +4559,6 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms)
4540 if (NILP (font)) 4559 if (NILP (font))
4541 error ("No suitable font was found"); 4560 error ("No suitable font was found");
4542 } 4561 }
4543 else if (!NILP (font_param))
4544 {
4545 /* Remember the explicit font parameter, so we can re-apply it after
4546 we've applied the `default' face settings. */
4547 AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
4548 gui_set_frame_parameters (f, arg);
4549 }
4550 4562
4551 /* This call will make X resources override any system font setting. */ 4563 /* This call will make X resources override any system font setting. */
4552 gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING); 4564 gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
diff --git a/src/xselect.c b/src/xselect.c
index db5c7853e7f..a381fa23522 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -918,6 +918,13 @@ x_handle_selection_request (struct selection_input_event *event)
918 } 918 }
919 /* Save conversion results */ 919 /* Save conversion results */
920 lisp_data_to_selection_data (dpyinfo, multprop, &cs); 920 lisp_data_to_selection_data (dpyinfo, multprop, &cs);
921
922 /* If cs.type is ATOM, change it to ATOM_PAIR. This is because
923 the parameters to a MULTIPLE are ATOM_PAIRs. */
924
925 if (cs.type == XA_ATOM)
926 cs.type = dpyinfo->Xatom_ATOM_PAIR;
927
921 XChangeProperty (dpyinfo->display, requestor, property, 928 XChangeProperty (dpyinfo->display, requestor, property,
922 cs.type, cs.format, PropModeReplace, 929 cs.type, cs.format, PropModeReplace,
923 cs.data, cs.size); 930 cs.data, cs.size);
@@ -960,7 +967,7 @@ x_handle_selection_request (struct selection_input_event *event)
960 x_reply_selection_request. If FOR_MULTIPLE, write out 967 x_reply_selection_request. If FOR_MULTIPLE, write out
961 the data even if conversion fails, using conversion_fail_tag. 968 the data even if conversion fails, using conversion_fail_tag.
962 969
963 Return true iff successful. */ 970 Return true if successful. */
964 971
965static bool 972static bool
966x_convert_selection (Lisp_Object selection_symbol, 973x_convert_selection (Lisp_Object selection_symbol,
diff --git a/src/xsettings.c b/src/xsettings.c
index 15e7ff54995..00b67539d41 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -56,6 +56,7 @@ typedef unsigned int CARD32;
56 56
57#ifdef USE_CAIRO 57#ifdef USE_CAIRO
58#include <fontconfig/fontconfig.h> 58#include <fontconfig/fontconfig.h>
59#include "ftfont.h"
59#elif defined HAVE_XFT 60#elif defined HAVE_XFT
60#include <X11/Xft/Xft.h> 61#include <X11/Xft/Xft.h>
61#endif 62#endif
@@ -765,7 +766,7 @@ parse_settings (unsigned char *prop,
765#ifndef HAVE_PGTK 766#ifndef HAVE_PGTK
766/* Read settings from the XSettings property window on display for DPYINFO. 767/* Read settings from the XSettings property window on display for DPYINFO.
767 Store settings read in SETTINGS. 768 Store settings read in SETTINGS.
768 Return true iff successful. */ 769 Return true if successful. */
769 770
770static bool 771static bool
771read_settings (Display_Info *dpyinfo, struct xsettings *settings) 772read_settings (Display_Info *dpyinfo, struct xsettings *settings)
@@ -826,6 +827,7 @@ apply_xft_settings (Display_Info *dpyinfo,
826#else 827#else
827 FcConfigSubstitute (NULL, pat, FcMatchPattern); 828 FcConfigSubstitute (NULL, pat, FcMatchPattern);
828 options = cairo_font_options_create (); 829 options = cairo_font_options_create ();
830 ftcrfont_get_default_font_options (dpyinfo, options);
829 cairo_ft_font_options_substitute (options, pat); 831 cairo_ft_font_options_substitute (options, pat);
830 cairo_font_options_destroy (options); 832 cairo_font_options_destroy (options);
831 FcDefaultSubstitute (pat); 833 FcDefaultSubstitute (pat);
@@ -884,6 +886,14 @@ apply_xft_settings (Display_Info *dpyinfo,
884 } 886 }
885#endif 887#endif
886 888
889#ifdef USE_CAIRO
890 /* When Cairo is being used, set oldsettings.dpi to dpyinfo->resx.
891 This is a gross hack, but seeing as Cairo fails to report
892 anything reasonable, just use it to avoid config-changed events
893 being sent at startup. */
894 oldsettings.dpi = dpyinfo->resx;
895#endif
896
887 if ((settings->seen & SEEN_DPI) != 0 897 if ((settings->seen & SEEN_DPI) != 0
888 && settings->dpi > 0 898 && settings->dpi > 0
889 /* The following conjunct avoids setting `changed' to true when 899 /* The following conjunct avoids setting `changed' to true when
diff --git a/src/xterm.c b/src/xterm.c
index 7dd969b821f..af652a0d856 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -912,11 +912,6 @@ struct x_selection_request_event
912 912
913struct x_selection_request_event *pending_selection_requests; 913struct x_selection_request_event *pending_selection_requests;
914 914
915/* Compare two request serials A and B with OP, handling
916 wraparound. */
917#define X_COMPARE_SERIALS(a, op ,b) \
918 (((long) (a) - (long) (b)) op 0)
919
920struct x_atom_ref 915struct x_atom_ref
921{ 916{
922 /* Atom name. */ 917 /* Atom name. */
@@ -1139,6 +1134,7 @@ static void x_clean_failable_requests (struct x_display_info *);
1139static struct frame *x_tooltip_window_to_frame (struct x_display_info *, 1134static struct frame *x_tooltip_window_to_frame (struct x_display_info *,
1140 Window, bool *); 1135 Window, bool *);
1141static Window x_get_window_below (Display *, Window, int, int, int *, int *); 1136static Window x_get_window_below (Display *, Window, int, int, int *, int *);
1137static void x_set_input_focus (struct x_display_info *, Window, Time);
1142 1138
1143#ifndef USE_TOOLKIT_SCROLL_BARS 1139#ifndef USE_TOOLKIT_SCROLL_BARS
1144static void x_scroll_bar_redraw (struct scroll_bar *); 1140static void x_scroll_bar_redraw (struct scroll_bar *);
@@ -5245,7 +5241,9 @@ xi_convert_button_state (XIButtonState *in, unsigned int *out)
5245 } 5241 }
5246} 5242}
5247 5243
5248/* Return the modifier state in XEV as a standard X modifier mask. */ 5244/* Return the modifier state in XEV as a standard X modifier mask.
5245 This should be used for non-keyboard events, where the group does
5246 not matter. */
5249 5247
5250#ifdef USE_GTK 5248#ifdef USE_GTK
5251static 5249static
@@ -5263,6 +5261,17 @@ xi_convert_event_state (XIDeviceEvent *xev)
5263 return mods | buttons; 5261 return mods | buttons;
5264} 5262}
5265 5263
5264/* Like the above. However, buttons are not converted, while the
5265 group is. This should be used for key events being passed to the
5266 likes of input methods and Xt. */
5267
5268static unsigned int
5269xi_convert_event_keyboard_state (XIDeviceEvent *xev)
5270{
5271 return ((xev->mods.effective & ~(1 << 13 | 1 << 14))
5272 | (xev->group.effective << 13));
5273}
5274
5266/* Free all XI2 devices on DPYINFO. */ 5275/* Free all XI2 devices on DPYINFO. */
5267static void 5276static void
5268x_free_xi_devices (struct x_display_info *dpyinfo) 5277x_free_xi_devices (struct x_display_info *dpyinfo)
@@ -5301,6 +5310,7 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
5301} 5310}
5302 5311
5303#ifdef HAVE_XINPUT2_1 5312#ifdef HAVE_XINPUT2_1
5313
5304struct xi_known_valuator 5314struct xi_known_valuator
5305{ 5315{
5306 /* The current value of this valuator. */ 5316 /* The current value of this valuator. */
@@ -5312,20 +5322,60 @@ struct xi_known_valuator
5312 /* The next valuator whose value we already know. */ 5322 /* The next valuator whose value we already know. */
5313 struct xi_known_valuator *next; 5323 struct xi_known_valuator *next;
5314}; 5324};
5325
5326/* Populate the scroll valuator at INDEX in DEVICE with the scroll
5327 valuator information provided in INFO.
5328
5329 The information consists of:
5330
5331 - whether or not the valuator is horizontal.
5332
5333 - whether or not the valuator's value is currently unknown,
5334 until the next XI_Motion event is received or the valuator's
5335 value is restored by the caller upon encountering valuator
5336 class data.
5337
5338 - what the current value of the valuator is. This is set to
5339 DBL_MIN for debugging purposes, but can be any value, as
5340 invalid_p is currently true.
5341
5342 - the increment, which defines the amount of movement equal to a
5343 single unit of scrolling. For example, if the increment is
5344 2.0, then a WHEEL_DOWN or WHEEL_UP event will be sent every
5345 time the valuator value changes by 2.0, unless
5346 mwheel-coalesce-scroll-events is nil.
5347
5348 - the number used in XI_Motion events and elsewhere to identify
5349 the valuator. */
5350
5351static void
5352xi_populate_scroll_valuator (struct xi_device_t *device,
5353 int index, XIScrollClassInfo *info)
5354{
5355 struct xi_scroll_valuator_t *valuator;
5356
5357 valuator = &device->valuators[index];
5358 valuator->horizontal
5359 = (info->scroll_type == XIScrollTypeHorizontal);
5360 valuator->invalid_p = true;
5361 valuator->emacs_value = DBL_MIN;
5362 valuator->increment = info->increment;
5363 valuator->number = info->number;
5364}
5365
5315#endif 5366#endif
5316 5367
5317static void 5368static void
5318xi_populate_device_from_info (struct xi_device_t *xi_device, 5369xi_populate_device_from_info (struct x_display_info *dpyinfo,
5370 struct xi_device_t *xi_device,
5319 XIDeviceInfo *device) 5371 XIDeviceInfo *device)
5320{ 5372{
5321#ifdef HAVE_XINPUT2_1 5373#ifdef HAVE_XINPUT2_1
5322 struct xi_scroll_valuator_t *valuator;
5323 struct xi_known_valuator *values, *tem; 5374 struct xi_known_valuator *values, *tem;
5324 int actual_valuator_count; 5375 int actual_valuator_count, c;
5325 XIScrollClassInfo *info; 5376 XIScrollClassInfo *info;
5326 XIValuatorClassInfo *val_info; 5377 XIValuatorClassInfo *valuator_info;
5327#endif 5378#endif
5328 int c;
5329#ifdef HAVE_XINPUT2_2 5379#ifdef HAVE_XINPUT2_2
5330 XITouchClassInfo *touch_info; 5380 XITouchClassInfo *touch_info;
5331#endif 5381#endif
@@ -5334,58 +5384,121 @@ xi_populate_device_from_info (struct xi_device_t *xi_device,
5334 USE_SAFE_ALLOCA; 5384 USE_SAFE_ALLOCA;
5335#endif 5385#endif
5336 5386
5387 /* Initialize generic information about the device: its ID, which
5388 buttons are currently pressed and thus presumably actively
5389 grabbing the device, what kind of device it is (master pointer,
5390 master keyboard, slave pointer, slave keyboard, or floating
5391 slave), and its attachment.
5392
5393 Here is a brief description of what device uses and attachments
5394 are. Under XInput 2, user input from individual input devices is
5395 multiplexed into specific seats before being delivered, with each
5396 seat corresponding to a single on-screen mouse pointer and having
5397 its own keyboard focus. Each seat consists of two virtual
5398 devices: the master keyboard and the master pointer, the first of
5399 which is used to report all keyboard input, with the other used
5400 to report all other input.
5401
5402 Input from each physical device (mouse, trackpad or keyboard) is
5403 then associated with that slave device's paired master device.
5404 For example, moving the device "Logitech USB Optical Mouse",
5405 enslaved by the master pointer device "Virtual core pointer",
5406 will result in movement of the mouse pointer associated with that
5407 master device's seat. If the pointer moves over an Emacs frame,
5408 then the frame will receive XI_Enter and XI_Motion events from
5409 that master pointer.
5410
5411 Likewise, keyboard input from the device "AT Translated Set 2
5412 keyboard", enslaved by the master keyboard device "Virtual core
5413 keyboard", will be reported to its seat's input focus window.
5414
5415 The device use describes what the device is. The meanings of
5416 MasterPointer, MasterKeyboard, SlavePointer and SlaveKeyboard
5417 should be obvious. FloatingSlave means the device is a slave
5418 device that is not associated with any seat, and thus generates
5419 no input.
5420
5421 The device attachment is a device ID whose meaning varies
5422 depending on the device use. If the device is a master device,
5423 then the attachment is the device ID of the other device in its
5424 seat (the master keyboard for master pointer devices, and vice
5425 versa). Otherwise, it is the ID of the master device the slave
5426 device is attached to. For slave devices not attached to any
5427 seat, its value is undefined. */
5428
5337 xi_device->device_id = device->deviceid; 5429 xi_device->device_id = device->deviceid;
5338 xi_device->grab = 0; 5430 xi_device->grab = 0;
5339
5340#ifdef HAVE_XINPUT2_1
5341 actual_valuator_count = 0;
5342 xi_device->valuators = xmalloc (sizeof *xi_device->valuators
5343 * device->num_classes);
5344 values = NULL;
5345#endif
5346
5347 xi_device->use = device->use; 5431 xi_device->use = device->use;
5348 xi_device->name = build_string (device->name); 5432 xi_device->name = build_string (device->name);
5349 xi_device->attachment = device->attachment; 5433 xi_device->attachment = device->attachment;
5350 5434
5435 /* Clear the list of active touch points on the device, which are
5436 individual touches tracked by a touchscreen. */
5437
5351#ifdef HAVE_XINPUT2_2 5438#ifdef HAVE_XINPUT2_2
5352 xi_device->touchpoints = NULL; 5439 xi_device->touchpoints = NULL;
5353 xi_device->direct_p = false; 5440 xi_device->direct_p = false;
5354#endif 5441#endif
5355 5442
5443#ifdef HAVE_XINPUT2_1
5444 if (!dpyinfo->xi2_version)
5445 {
5446 /* Skip everything below as there are no classes of interest on
5447 XI 2.0 servers. */
5448 xi_device->valuators = NULL;
5449 xi_device->scroll_valuator_count = 0;
5450
5451 SAFE_FREE ();
5452 return;
5453 }
5454
5455 actual_valuator_count = 0;
5456 xi_device->valuators = xnmalloc (device->num_classes,
5457 sizeof *xi_device->valuators);
5458 values = NULL;
5459
5460 /* Initialize device info based on a list of "device classes".
5461 Device classes are little pieces of information associated with a
5462 device. Emacs is interested in scroll valuator information and
5463 touch handling information, which respectively describe the axes
5464 (if any) along which the device's scroll wheel rotates, and how
5465 the device reports touch input. */
5466
5356 for (c = 0; c < device->num_classes; ++c) 5467 for (c = 0; c < device->num_classes; ++c)
5357 { 5468 {
5358 switch (device->classes[c]->type) 5469 switch (device->classes[c]->type)
5359 { 5470 {
5360#ifdef HAVE_XINPUT2_1
5361 case XIScrollClass: 5471 case XIScrollClass:
5362 { 5472 {
5363 info = (XIScrollClassInfo *) device->classes[c]; 5473 info = (XIScrollClassInfo *) device->classes[c];
5364 5474 xi_populate_scroll_valuator (xi_device, actual_valuator_count++,
5365 valuator = &xi_device->valuators[actual_valuator_count++]; 5475 info);
5366 valuator->horizontal
5367 = (info->scroll_type == XIScrollTypeHorizontal);
5368 valuator->invalid_p = true;
5369 valuator->emacs_value = DBL_MIN;
5370 valuator->increment = info->increment;
5371 valuator->number = info->number;
5372
5373 break; 5476 break;
5374 } 5477 }
5375 5478
5376 case XIValuatorClass: 5479 case XIValuatorClass:
5377 { 5480 {
5378 val_info = (XIValuatorClassInfo *) device->classes[c]; 5481 valuator_info = (XIValuatorClassInfo *) device->classes[c];
5379 tem = SAFE_ALLOCA (sizeof *tem); 5482 tem = SAFE_ALLOCA (sizeof *tem);
5380 5483
5484 /* Avoid restoring bogus values if some driver
5485 accidentally specifies relative values in scroll
5486 valuator classes how the input extension spec says they
5487 should be, but allow restoring values when a value is
5488 set, which is how the input extension actually
5489 behaves. */
5490
5491 if (valuator_info->value == 0.0
5492 && valuator_info->mode != XIModeAbsolute)
5493 continue;
5494
5381 tem->next = values; 5495 tem->next = values;
5382 tem->number = val_info->number; 5496 tem->number = valuator_info->number;
5383 tem->current_value = val_info->value; 5497 tem->current_value = valuator_info->value;
5384 5498
5385 values = tem; 5499 values = tem;
5386 break; 5500 break;
5387 } 5501 }
5388#endif
5389 5502
5390#ifdef HAVE_XINPUT2_2 5503#ifdef HAVE_XINPUT2_2
5391 case XITouchClass: 5504 case XITouchClass:
@@ -5399,7 +5512,6 @@ xi_populate_device_from_info (struct xi_device_t *xi_device,
5399 } 5512 }
5400 } 5513 }
5401 5514
5402#ifdef HAVE_XINPUT2_1
5403 xi_device->scroll_valuator_count = actual_valuator_count; 5515 xi_device->scroll_valuator_count = actual_valuator_count;
5404 5516
5405 /* Now look through all the valuators whose values are already known 5517 /* Now look through all the valuators whose values are already known
@@ -5413,7 +5525,9 @@ xi_populate_device_from_info (struct xi_device_t *xi_device,
5413 if (xi_device->valuators[c].number == tem->number) 5525 if (xi_device->valuators[c].number == tem->number)
5414 { 5526 {
5415 xi_device->valuators[c].invalid_p = false; 5527 xi_device->valuators[c].invalid_p = false;
5416 xi_device->valuators[c].current_value = tem->current_value; 5528 xi_device->valuators[c].current_value
5529 = tem->current_value;
5530 xi_device->valuators[c].emacs_value = 0.0;
5417 } 5531 }
5418 } 5532 }
5419 } 5533 }
@@ -5475,7 +5589,8 @@ x_cache_xi_devices (struct x_display_info *dpyinfo)
5475 for (i = 0; i < ndevices; ++i) 5589 for (i = 0; i < ndevices; ++i)
5476 { 5590 {
5477 if (infos[i].enabled) 5591 if (infos[i].enabled)
5478 xi_populate_device_from_info (&dpyinfo->devices[actual_devices++], 5592 xi_populate_device_from_info (dpyinfo,
5593 &dpyinfo->devices[actual_devices++],
5479 &infos[i]); 5594 &infos[i]);
5480 } 5595 }
5481 5596
@@ -5610,8 +5725,11 @@ static void
5610xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, 5725xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo,
5611 int id) 5726 int id)
5612{ 5727{
5613 struct xi_device_t *device = xi_device_from_id (dpyinfo, id); 5728 struct xi_device_t *device;
5614 struct xi_scroll_valuator_t *valuator; 5729 struct xi_scroll_valuator_t *valuator;
5730 int i;
5731
5732 device = xi_device_from_id (dpyinfo, id);
5615 5733
5616 if (!device) 5734 if (!device)
5617 return; 5735 return;
@@ -5619,7 +5737,7 @@ xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo,
5619 if (!device->scroll_valuator_count) 5737 if (!device->scroll_valuator_count)
5620 return; 5738 return;
5621 5739
5622 for (int i = 0; i < device->scroll_valuator_count; ++i) 5740 for (i = 0; i < device->scroll_valuator_count; ++i)
5623 { 5741 {
5624 valuator = &device->valuators[i]; 5742 valuator = &device->valuators[i];
5625 valuator->invalid_p = true; 5743 valuator->invalid_p = true;
@@ -11414,15 +11532,18 @@ x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
11414 x_frame_rehighlight (dpyinfo); 11532 x_frame_rehighlight (dpyinfo);
11415} 11533}
11416 11534
11535#ifdef HAVE_XFIXES
11536
11417/* True if the display in DPYINFO supports a version of Xfixes 11537/* True if the display in DPYINFO supports a version of Xfixes
11418 sufficient for pointer blanking. */ 11538 sufficient for pointer blanking. */
11419#ifdef HAVE_XFIXES 11539
11420static bool 11540static bool
11421x_probe_xfixes_extension (struct x_display_info *dpyinfo) 11541x_fixes_pointer_blanking_supported (struct x_display_info *dpyinfo)
11422{ 11542{
11423 return (dpyinfo->xfixes_supported_p 11543 return (dpyinfo->xfixes_supported_p
11424 && dpyinfo->xfixes_major >= 4); 11544 && dpyinfo->xfixes_major >= 4);
11425} 11545}
11546
11426#endif /* HAVE_XFIXES */ 11547#endif /* HAVE_XFIXES */
11427 11548
11428/* Toggle mouse pointer visibility on frame F using the XFixes 11549/* Toggle mouse pointer visibility on frame F using the XFixes
@@ -11493,7 +11614,7 @@ x_toggle_visible_pointer (struct frame *f, bool invisible)
11493 /* But if Xfixes is available, try using it instead. */ 11614 /* But if Xfixes is available, try using it instead. */
11494 if (dpyinfo->invisible_cursor == None) 11615 if (dpyinfo->invisible_cursor == None)
11495 { 11616 {
11496 if (x_probe_xfixes_extension (dpyinfo)) 11617 if (x_fixes_pointer_blanking_supported (dpyinfo))
11497 { 11618 {
11498 dpyinfo->fixes_pointer_blanking = true; 11619 dpyinfo->fixes_pointer_blanking = true;
11499 xfixes_toggle_visible_pointer (f, invisible); 11620 xfixes_toggle_visible_pointer (f, invisible);
@@ -11521,7 +11642,7 @@ XTtoggle_invisible_pointer (struct frame *f, bool invisible)
11521 block_input (); 11642 block_input ();
11522#ifdef HAVE_XFIXES 11643#ifdef HAVE_XFIXES
11523 if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking 11644 if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking
11524 && x_probe_xfixes_extension (FRAME_DISPLAY_INFO (f))) 11645 && x_fixes_pointer_blanking_supported (FRAME_DISPLAY_INFO (f)))
11525 xfixes_toggle_visible_pointer (f, invisible); 11646 xfixes_toggle_visible_pointer (f, invisible);
11526 else 11647 else
11527#endif 11648#endif
@@ -11529,13 +11650,16 @@ XTtoggle_invisible_pointer (struct frame *f, bool invisible)
11529 unblock_input (); 11650 unblock_input ();
11530} 11651}
11531 11652
11532/* Handle FocusIn and FocusOut state changes for FRAME. 11653/* Handle FocusIn and FocusOut state changes for FRAME. If FRAME has
11533 If FRAME has focus and there exists more than one frame, puts 11654 focus and there exists more than one frame, puts a FOCUS_IN_EVENT
11534 a FOCUS_IN_EVENT into *BUFP. */ 11655 into *BUFP. Note that this code is not used to handle focus
11656 changes on builds that can use the X Input extension for handling
11657 input focus when it is available (currently the no toolkit and GTK
11658 3 toolkits). */
11535 11659
11536static void 11660static void
11537x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, 11661x_focus_changed (int type, int state, struct x_display_info *dpyinfo,
11538 struct input_event *bufp) 11662 struct frame *frame, struct input_event *bufp)
11539{ 11663{
11540 if (type == FocusIn) 11664 if (type == FocusIn)
11541 { 11665 {
@@ -13017,121 +13141,181 @@ xi_get_scroll_valuator (struct xi_device_t *device, int number)
13017 return NULL; 13141 return NULL;
13018} 13142}
13019 13143
13020#endif 13144/* Check if EVENT, a DeviceChanged event, contains any scroll
13145 valuators. */
13021 13146
13022/* Handle EVENT, a DeviceChanged event. Look up the device that 13147static bool
13023 changed, and update its information with the data in EVENT. */ 13148xi_has_scroll_valuators (XIDeviceChangedEvent *event)
13149{
13150 int i;
13151
13152 for (i = 0; i < event->num_classes; ++i)
13153 {
13154 if (event->classes[i]->type == XIScrollClass)
13155 return true;
13156 }
13157
13158 return false;
13159}
13160
13161/* Repopulate the information (touchpoint tracking information, scroll
13162 valuators, etc) in DEVICE with the device classes provided in
13163 CLASSES. This is called upon receiving a DeviceChanged event.
13164
13165 This function is not present on XI 2.0 as there are no worthwhile
13166 classes there. */
13024 13167
13025static void 13168static void
13026xi_handle_device_changed (struct x_display_info *dpyinfo, 13169xi_handle_new_classes (struct x_display_info *dpyinfo, struct xi_device_t *device,
13027 struct xi_device_t *device, 13170 XIAnyClassInfo **classes, int num_classes)
13028 XIDeviceChangedEvent *event)
13029{ 13171{
13030#ifdef HAVE_XINPUT2_1
13031 XIDeviceInfo *info;
13032 XIScrollClassInfo *scroll; 13172 XIScrollClassInfo *scroll;
13033 int i, ndevices;
13034 struct xi_scroll_valuator_t *valuator; 13173 struct xi_scroll_valuator_t *valuator;
13035 XIValuatorClassInfo *valuator_info; 13174 XIValuatorClassInfo *valuator_info;
13036#endif 13175 int i;
13037#ifdef HAVE_XINPUT2_2 13176#ifdef HAVE_XINPUT2_2
13038 struct xi_touch_point_t *tem, *last;
13039 XITouchClassInfo *touch; 13177 XITouchClassInfo *touch;
13040#endif 13178#endif
13041 13179
13042#ifdef HAVE_XINPUT2_1 13180 if (dpyinfo->xi2_version < 1)
13043 /* When a DeviceChange event is received for a master device, we 13181 /* Emacs is connected to an XI 2.0 server, which reports no
13044 don't get any scroll valuators along with it. This is possibly 13182 classes of interest. */
13045 an X server bug but I really don't want to dig any further, so 13183 return;
13046 fetch the scroll valuators manually. (bug#57020) */
13047
13048 x_catch_errors (dpyinfo->display);
13049 info = XIQueryDevice (dpyinfo->display, event->deviceid,
13050 /* ndevices is always 1 if a deviceid is
13051 specified. If the request fails, NULL will
13052 be returned. */
13053 &ndevices);
13054 x_uncatch_errors ();
13055 13184
13056 if (info) 13185 device->valuators = xnmalloc (num_classes,
13057 { 13186 sizeof *device->valuators);
13058 device->valuators = xrealloc (device->valuators, 13187 device->scroll_valuator_count = 0;
13059 (info->num_classes
13060 * sizeof *device->valuators));
13061 device->scroll_valuator_count = 0;
13062#ifdef HAVE_XINPUT2_2 13188#ifdef HAVE_XINPUT2_2
13063 device->direct_p = false; 13189 device->direct_p = false;
13064#endif 13190#endif
13065 13191
13066 for (i = 0; i < info->num_classes; ++i) 13192 for (i = 0; i < num_classes; ++i)
13193 {
13194 switch (classes[i]->type)
13067 { 13195 {
13068 switch (info->classes[i]->type) 13196 case XIScrollClass:
13069 { 13197 scroll = (XIScrollClassInfo *) classes[i];
13070 case XIScrollClass: 13198
13071 scroll = (XIScrollClassInfo *) info->classes[i]; 13199 xi_populate_scroll_valuator (device,
13072 13200 device->scroll_valuator_count++,
13073 valuator = &device->valuators[device->scroll_valuator_count++]; 13201 scroll);
13074 valuator->horizontal = (scroll->scroll_type 13202 break;
13075 == XIScrollTypeHorizontal);
13076 valuator->invalid_p = true;
13077 valuator->emacs_value = DBL_MIN;
13078 valuator->increment = scroll->increment;
13079 valuator->number = scroll->number;
13080 break;
13081 13203
13082#ifdef HAVE_XINPUT2_2 13204#ifdef HAVE_XINPUT2_2
13083 case XITouchClass: 13205 case XITouchClass:
13084 touch = (XITouchClassInfo *) info->classes[i]; 13206 touch = (XITouchClassInfo *) classes[i];
13085 13207
13086 if (touch->mode == XIDirectTouch) 13208 if (touch->mode == XIDirectTouch)
13087 device->direct_p = true; 13209 device->direct_p = true;
13088 break; 13210 break;
13089#endif 13211#endif
13090 }
13091 } 13212 }
13213 }
13092 13214
13093 /* Restore the values of any scroll valuators that we already 13215 /* Restore the values of any scroll valuators that we already
13094 know about. */ 13216 know about. */
13095 13217
13096 for (i = 0; i < info->num_classes; ++i) 13218 for (i = 0; i < num_classes; ++i)
13097 { 13219 {
13098 switch (info->classes[i]->type) 13220 if (classes[i]->type != XIValuatorClass)
13099 { 13221 continue;
13100 case XIValuatorClass:
13101 valuator_info = (XIValuatorClassInfo *) info->classes[i];
13102 13222
13103 valuator = xi_get_scroll_valuator (device, 13223 valuator_info = (XIValuatorClassInfo *) classes[i];
13104 valuator_info->number);
13105 if (valuator)
13106 {
13107 valuator->invalid_p = false;
13108 valuator->current_value = valuator_info->value;
13109 }
13110 13224
13111 break; 13225 /* Avoid restoring bogus values if some driver accidentally
13112 } 13226 specifies relative values in scroll valuator classes how the
13113 } 13227 input extension spec says they should be, but allow restoring
13228 values when a value is set, which is how the input extension
13229 actually behaves. */
13230
13231 if (valuator_info->value == 0.0
13232 && valuator_info->mode != XIModeAbsolute)
13233 continue;
13234
13235 valuator = xi_get_scroll_valuator (device,
13236 valuator_info->number);
13237
13238 if (!valuator)
13239 continue;
13240
13241 valuator->invalid_p = false;
13242 valuator->current_value = valuator_info->value;
13243 valuator->emacs_value = 0;
13114 13244
13245 break;
13246 }
13247}
13248
13249#endif
13250
13251/* Handle EVENT, a DeviceChanged event. Look up the device that
13252 changed, and update its information with the data in EVENT. */
13253
13254static void
13255xi_handle_device_changed (struct x_display_info *dpyinfo,
13256 struct xi_device_t *device,
13257 XIDeviceChangedEvent *event)
13258{
13259#ifdef HAVE_XINPUT2_1
13260 int ndevices;
13261 XIDeviceInfo *info;
13262#endif
13115#ifdef HAVE_XINPUT2_2 13263#ifdef HAVE_XINPUT2_2
13116 /* The device is no longer a DirectTouch device, so 13264 struct xi_touch_point_t *tem, *last;
13117 remove any touchpoints that we might have 13265#endif
13118 recorded. */
13119 if (!device->direct_p)
13120 {
13121 tem = device->touchpoints;
13122 13266
13123 while (tem) 13267#ifdef HAVE_XINPUT2_1
13124 { 13268 if (xi_has_scroll_valuators (event))
13125 last = tem; 13269 /* Scroll valuators are provided by this event. Use the values
13126 tem = tem->next; 13270 provided in this event to populate the device's new scroll
13127 xfree (last); 13271 valuator list: if this event is a SlaveSwitch event caused by
13128 } 13272 wheel movement, then querying for the device info will probably
13273 return the value after the wheel movement, leading to a delta
13274 of 0 being computed upon handling the subsequent XI_Motion
13275 event. (bug#58980) */
13276 xi_handle_new_classes (dpyinfo, device, event->classes,
13277 event->num_classes);
13278 else
13279 {
13280 /* When a DeviceChange event is received for a master device,
13281 the X server sometimes does not send any scroll valuators
13282 along with it. This is possibly an X server bug but I really
13283 don't want to dig any further, so fetch the scroll valuators
13284 manually. (bug#57020) */
13129 13285
13130 device->touchpoints = NULL; 13286 x_catch_errors (dpyinfo->display);
13131 } 13287 info = XIQueryDevice (dpyinfo->display, event->deviceid,
13288 /* ndevices is always 1 if a deviceid is
13289 specified. If the request fails, NULL will
13290 be returned. */
13291 &ndevices);
13292 x_uncatch_errors ();
13293
13294 if (!info)
13295 return;
13296
13297 /* info contains the classes currently associated with the
13298 event. Apply them. */
13299 xi_handle_new_classes (dpyinfo, device, info->classes,
13300 info->num_classes);
13301 }
13132#endif 13302#endif
13133 13303
13134 XIFreeDeviceInfo (info); 13304#ifdef HAVE_XINPUT2_2
13305 /* The device is no longer a DirectTouch device, so remove any
13306 touchpoints that we might have recorded. */
13307 if (!device->direct_p)
13308 {
13309 tem = device->touchpoints;
13310
13311 while (tem)
13312 {
13313 last = tem;
13314 tem = tem->next;
13315 xfree (last);
13316 }
13317
13318 device->touchpoints = NULL;
13135 } 13319 }
13136#endif 13320#endif
13137} 13321}
@@ -13383,7 +13567,7 @@ x_find_modifier_meanings (struct x_display_info *dpyinfo)
13383#ifdef HAVE_XKB 13567#ifdef HAVE_XKB
13384 int i; 13568 int i;
13385 int found_meta_p = false; 13569 int found_meta_p = false;
13386 uint vmodmask; 13570 unsigned int vmodmask;
13387#endif 13571#endif
13388 13572
13389 dpyinfo->meta_mod_mask = 0; 13573 dpyinfo->meta_mod_mask = 0;
@@ -14079,6 +14263,136 @@ x_get_window_below (Display *dpy, Window window,
14079 return value; 14263 return value;
14080} 14264}
14081 14265
14266/* Like XTmouse_position, but much faster. */
14267
14268static void
14269x_fast_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14270 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
14271 Time *timestamp)
14272{
14273 int root_x, root_y, win_x, win_y;
14274 unsigned int mask;
14275 Window dummy;
14276 struct scroll_bar *bar;
14277 struct x_display_info *dpyinfo;
14278 Lisp_Object tail, frame;
14279 struct frame *f1;
14280
14281 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14282
14283 if (dpyinfo->last_mouse_scroll_bar && !insist)
14284 {
14285 bar = dpyinfo->last_mouse_scroll_bar;
14286
14287 if (bar->horizontal)
14288 x_horizontal_scroll_bar_report_motion (fp, bar_window, part,
14289 x, y, timestamp);
14290 else
14291 x_scroll_bar_report_motion (fp, bar_window, part,
14292 x, y, timestamp);
14293
14294 return;
14295 }
14296
14297 if (!EQ (Vx_use_fast_mouse_position, Qreally_fast))
14298 {
14299 /* This means that Emacs should select a frame and report the
14300 mouse position relative to it. The approach used here avoids
14301 making multiple roundtrips to the X server querying for the
14302 window beneath the pointer, and was borrowed from
14303 haiku_mouse_position in haikuterm.c. */
14304
14305 FOR_EACH_FRAME (tail, frame)
14306 {
14307 if (FRAME_X_P (XFRAME (frame))
14308 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14309 == dpyinfo))
14310 XFRAME (frame)->mouse_moved = false;
14311 }
14312
14313 if (gui_mouse_grabbed (dpyinfo)
14314 && !EQ (track_mouse, Qdropping)
14315 && !EQ (track_mouse, Qdrag_source))
14316 /* Pick the last mouse frame if dropping. */
14317 f1 = dpyinfo->last_mouse_frame;
14318 else
14319 /* Otherwise, pick the last mouse motion frame. */
14320 f1 = dpyinfo->last_mouse_motion_frame;
14321
14322 if (!f1 && (FRAME_X_P (SELECTED_FRAME ())
14323 && (FRAME_DISPLAY_INFO (SELECTED_FRAME ())
14324 == dpyinfo)))
14325 f1 = SELECTED_FRAME ();
14326
14327 if (!f1 || (!FRAME_X_P (f1) && (insist > 0)))
14328 FOR_EACH_FRAME (tail, frame)
14329 if (FRAME_X_P (XFRAME (frame))
14330 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14331 == dpyinfo)
14332 && !FRAME_TOOLTIP_P (XFRAME (frame)))
14333 f1 = XFRAME (frame);
14334
14335 if (f1 && FRAME_TOOLTIP_P (f1))
14336 f1 = NULL;
14337
14338 if (f1 && FRAME_X_P (f1) && FRAME_X_WINDOW (f1))
14339 {
14340 if (!x_query_pointer (dpyinfo->display, FRAME_X_WINDOW (f1),
14341 &dummy, &dummy, &root_x, &root_y,
14342 &win_x, &win_y, &mask))
14343 /* The pointer is out of the screen. */
14344 return;
14345
14346 remember_mouse_glyph (f1, win_x, win_y,
14347 &dpyinfo->last_mouse_glyph);
14348 dpyinfo->last_mouse_glyph_frame = f1;
14349
14350 *bar_window = Qnil;
14351 *part = scroll_bar_nowhere;
14352
14353 /* If track-mouse is `drag-source' and the mouse pointer is
14354 certain to not be actually under the chosen frame, return
14355 NULL in FP. */
14356 if (EQ (track_mouse, Qdrag_source)
14357 && (win_x < 0 || win_y < 0
14358 || win_x >= FRAME_PIXEL_WIDTH (f1)
14359 || win_y >= FRAME_PIXEL_HEIGHT (f1)))
14360 *fp = NULL;
14361 else
14362 *fp = f1;
14363
14364 *timestamp = dpyinfo->last_mouse_movement_time;
14365 XSETINT (*x, win_x);
14366 XSETINT (*y, win_y);
14367 }
14368 }
14369 else
14370 {
14371 /* This means Emacs should only report the coordinates of the
14372 last mouse motion. */
14373
14374 if (dpyinfo->last_mouse_motion_frame)
14375 {
14376 *fp = dpyinfo->last_mouse_motion_frame;
14377 *timestamp = dpyinfo->last_mouse_movement_time;
14378 *x = make_fixnum (dpyinfo->last_mouse_motion_x);
14379 *y = make_fixnum (dpyinfo->last_mouse_motion_y);
14380 *bar_window = Qnil;
14381 *part = scroll_bar_nowhere;
14382
14383 FOR_EACH_FRAME (tail, frame)
14384 {
14385 if (FRAME_X_P (XFRAME (frame))
14386 && (FRAME_DISPLAY_INFO (XFRAME (frame))
14387 == dpyinfo))
14388 XFRAME (frame)->mouse_moved = false;
14389 }
14390
14391 dpyinfo->last_mouse_motion_frame->mouse_moved = false;
14392 }
14393 }
14394}
14395
14082/* Return the current position of the mouse. 14396/* Return the current position of the mouse.
14083 *FP should be a frame which indicates which display to ask about. 14397 *FP should be a frame which indicates which display to ask about.
14084 14398
@@ -14105,9 +14419,27 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14105 Time *timestamp) 14419 Time *timestamp)
14106{ 14420{
14107 struct frame *f1, *maybe_tooltip; 14421 struct frame *f1, *maybe_tooltip;
14108 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); 14422 struct x_display_info *dpyinfo;
14109 bool unrelated_tooltip; 14423 bool unrelated_tooltip;
14110 14424
14425 dpyinfo = FRAME_DISPLAY_INFO (*fp);
14426
14427 if (!NILP (Vx_use_fast_mouse_position))
14428 {
14429 /* The user says that Emacs is running over the network, and a
14430 fast approximation of `mouse-position' should be used.
14431
14432 Depending on what the value of `x-use-fast-mouse-position'
14433 is, do one of two things: only perform the XQueryPointer to
14434 obtain the coordinates from the last mouse frame, or only
14435 return the last mouse motion frame and the
14436 last_mouse_motion_x and Y. */
14437
14438 x_fast_mouse_position (fp, insist, bar_window, part, x,
14439 y, timestamp);
14440 return;
14441 }
14442
14111 block_input (); 14443 block_input ();
14112 14444
14113 if (dpyinfo->last_mouse_scroll_bar && insist == 0) 14445 if (dpyinfo->last_mouse_scroll_bar && insist == 0)
@@ -14229,7 +14561,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14229 break; 14561 break;
14230 } 14562 }
14231#ifdef USE_GTK 14563#ifdef USE_GTK
14232 /* We don't wan't to know the innermost window. We 14564 /* We don't want to know the innermost window. We
14233 want the edit window. For non-Gtk+ the innermost 14565 want the edit window. For non-Gtk+ the innermost
14234 window is the edit window. For Gtk+ it might not 14566 window is the edit window. For Gtk+ it might not
14235 be. It might be the tool bar for example. */ 14567 be. It might be the tool bar for example. */
@@ -14260,7 +14592,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
14260 never use them in that case.) */ 14592 never use them in that case.) */
14261 14593
14262#ifdef USE_GTK 14594#ifdef USE_GTK
14263 /* We don't wan't to know the innermost window. We 14595 /* We don't want to know the innermost window. We
14264 want the edit window. */ 14596 want the edit window. */
14265 f1 = x_window_to_frame (dpyinfo, win); 14597 f1 = x_window_to_frame (dpyinfo, win);
14266#else 14598#else
@@ -18620,7 +18952,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
18620 18952
18621 /* If drag-and-drop or another modal dialog/menu is in 18953 /* If drag-and-drop or another modal dialog/menu is in
18622 progress, handle SelectionRequest events immediately, by 18954 progress, handle SelectionRequest events immediately, by
18623 pushing it onto the selecction queue. */ 18955 pushing it onto the selection queue. */
18624 18956
18625 if (x_use_pending_selection_requests) 18957 if (x_use_pending_selection_requests)
18626 { 18958 {
@@ -20980,8 +21312,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20980 21312
20981 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf))) 21313 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
20982 { 21314 {
21315 x_ignore_errors_for_next_request (dpyinfo);
20983 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 21316 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
20984 RevertToParent, event->xbutton.time); 21317 RevertToParent, event->xbutton.time);
21318 x_stop_ignoring_errors (dpyinfo);
21319
20985 if (FRAME_PARENT_FRAME (f)) 21320 if (FRAME_PARENT_FRAME (f))
20986 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); 21321 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
20987 } 21322 }
@@ -21393,6 +21728,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21393 related to those grabs arrive. The only way to 21728 related to those grabs arrive. The only way to
21394 remedy this is to never reset scroll valuators on a 21729 remedy this is to never reset scroll valuators on a
21395 grab-related crossing event. (bug#57476) */ 21730 grab-related crossing event. (bug#57476) */
21731
21396 if (enter->mode != XINotifyUngrab 21732 if (enter->mode != XINotifyUngrab
21397 && enter->mode != XINotifyGrab 21733 && enter->mode != XINotifyGrab
21398 && enter->mode != XINotifyPassiveGrab 21734 && enter->mode != XINotifyPassiveGrab
@@ -21522,17 +21858,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21522 was very complicated and kept running into server 21858 was very complicated and kept running into server
21523 bugs. */ 21859 bugs. */
21524#ifdef HAVE_XINPUT2_1 21860#ifdef HAVE_XINPUT2_1
21525 if (any 21861 /* xfwm4 selects for button events on the frame window,
21526 /* xfwm4 selects for button events on the frame 21862 resulting in passive grabs being generated along with
21527 window, resulting in passive grabs being 21863 the delivery of emulated button events; this then
21528 generated along with the delivery of emulated 21864 interferes with scrolling, since device valuators
21529 button events; this then interferes with 21865 will constantly be reset as the crossing events
21530 scrolling, since device valuators will constantly 21866 related to those grabs arrive. The only way to
21531 be reset as the crossing events related to those 21867 remedy this is to never reset scroll valuators on a
21532 grabs arrive. The only way to remedy this is to 21868 grab-related crossing event. (bug#57476) */
21533 never reset scroll valuators on a grab-related 21869
21534 crossing event. (bug#57476) */ 21870 if (leave->mode != XINotifyUngrab
21535 && leave->mode != XINotifyUngrab
21536 && leave->mode != XINotifyGrab 21871 && leave->mode != XINotifyGrab
21537 && leave->mode != XINotifyPassiveUngrab 21872 && leave->mode != XINotifyPassiveUngrab
21538 && leave->mode != XINotifyPassiveGrab) 21873 && leave->mode != XINotifyPassiveGrab)
@@ -21569,19 +21904,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21569 masks are set on the frame widget's window. */ 21904 masks are set on the frame widget's window. */
21570 f = x_window_to_frame (dpyinfo, leave->event); 21905 f = x_window_to_frame (dpyinfo, leave->event);
21571 21906
21572 /* Also do this again here, since the test for `any'
21573 above may not have found a frame, as that usually
21574 just looks up a top window on Xt builds. */
21575
21576#ifdef HAVE_XINPUT2_1
21577 if (f && leave->mode != XINotifyUngrab
21578 && leave->mode != XINotifyGrab
21579 && leave->mode != XINotifyPassiveUngrab
21580 && leave->mode != XINotifyPassiveGrab)
21581 xi_reset_scroll_valuators_for_device_id (dpyinfo,
21582 leave->deviceid);
21583#endif
21584
21585 if (!f) 21907 if (!f)
21586 f = x_top_window_to_frame (dpyinfo, leave->event); 21908 f = x_top_window_to_frame (dpyinfo, leave->event);
21587#endif 21909#endif
@@ -22696,9 +23018,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22696 } 23018 }
22697#else 23019#else
22698 /* Non-no toolkit builds without GTK 3 use core 23020 /* Non-no toolkit builds without GTK 3 use core
22699 events to handle focus. */ 23021 events to handle focus. Errors are still
23022 caught here in case the window is not
23023 viewable. */
23024 x_ignore_errors_for_next_request (dpyinfo);
22700 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 23025 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
22701 RevertToParent, xev->time); 23026 RevertToParent, xev->time);
23027 x_stop_ignoring_errors (dpyinfo);
22702#endif 23028#endif
22703 if (FRAME_PARENT_FRAME (f)) 23029 if (FRAME_PARENT_FRAME (f))
22704 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); 23030 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
@@ -22953,7 +23279,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22953 char *copy_bufptr = copy_buffer; 23279 char *copy_bufptr = copy_buffer;
22954 int copy_bufsiz = sizeof (copy_buffer); 23280 int copy_bufsiz = sizeof (copy_buffer);
22955 ptrdiff_t i; 23281 ptrdiff_t i;
22956 uint old_state; 23282 unsigned int old_state;
22957 struct xi_device_t *device, *source; 23283 struct xi_device_t *device, *source;
22958 23284
22959 coding = Qlatin_1; 23285 coding = Qlatin_1;
@@ -22979,8 +23305,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22979 copy.xkey.root = xev->root; 23305 copy.xkey.root = xev->root;
22980 copy.xkey.subwindow = xev->child; 23306 copy.xkey.subwindow = xev->child;
22981 copy.xkey.time = xev->time; 23307 copy.xkey.time = xev->time;
22982 copy.xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14)) 23308 copy.xkey.state = xi_convert_event_keyboard_state (xev);
22983 | (xev->group.effective << 13));
22984 xi_convert_button_state (&xev->buttons, &copy.xkey.state); 23309 xi_convert_button_state (&xev->buttons, &copy.xkey.state);
22985 23310
22986 copy.xkey.x = lrint (xev->event_x); 23311 copy.xkey.x = lrint (xev->event_x);
@@ -23036,8 +23361,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23036 xkey.root = xev->root; 23361 xkey.root = xev->root;
23037 xkey.subwindow = xev->child; 23362 xkey.subwindow = xev->child;
23038 xkey.time = xev->time; 23363 xkey.time = xev->time;
23039 xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14)) 23364 xkey.state = xi_convert_event_keyboard_state (xev);
23040 | (xev->group.effective << 13));
23041 23365
23042 xkey.x = lrint (xev->event_x); 23366 xkey.x = lrint (xev->event_x);
23043 xkey.y = lrint (xev->event_y); 23367 xkey.y = lrint (xev->event_y);
@@ -23101,8 +23425,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23101#ifdef HAVE_XKB 23425#ifdef HAVE_XKB
23102 if (dpyinfo->xkb_desc) 23426 if (dpyinfo->xkb_desc)
23103 { 23427 {
23104 uint xkb_state = state; 23428 unsigned int xkb_state;
23105 xkb_state &= ~(1 << 13 | 1 << 14); 23429
23430 xkb_state = state & ~(1 << 13 | 1 << 14);
23106 xkb_state |= xev->group.effective << 13; 23431 xkb_state |= xev->group.effective << 13;
23107 23432
23108 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode, 23433 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode,
@@ -23455,8 +23780,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23455 xkey.root = xev->root; 23780 xkey.root = xev->root;
23456 xkey.subwindow = xev->child; 23781 xkey.subwindow = xev->child;
23457 xkey.time = xev->time; 23782 xkey.time = xev->time;
23458 xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14)) 23783 xkey.state = xi_convert_event_keyboard_state (xev);
23459 | (xev->group.effective << 13));
23460 xkey.x = lrint (xev->event_x); 23784 xkey.x = lrint (xev->event_x);
23461 xkey.y = lrint (xev->event_y); 23785 xkey.y = lrint (xev->event_y);
23462 xkey.x_root = lrint (xev->root_x); 23786 xkey.x_root = lrint (xev->root_x);
@@ -23558,7 +23882,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23558 memset (dpyinfo->devices + dpyinfo->num_devices - 1, 23882 memset (dpyinfo->devices + dpyinfo->num_devices - 1,
23559 0, sizeof *dpyinfo->devices); 23883 0, sizeof *dpyinfo->devices);
23560 device = &dpyinfo->devices[dpyinfo->num_devices - 1]; 23884 device = &dpyinfo->devices[dpyinfo->num_devices - 1];
23561 xi_populate_device_from_info (device, info); 23885 xi_populate_device_from_info (dpyinfo, device, info);
23562 } 23886 }
23563 23887
23564 if (info) 23888 if (info)
@@ -24939,6 +25263,48 @@ static struct x_error_message_stack *x_error_message;
24939/* The amount of items (depth) in that stack. */ 25263/* The amount of items (depth) in that stack. */
24940int x_error_message_count; 25264int x_error_message_count;
24941 25265
25266/* Compare various request serials while handling wraparound. Treat a
25267 difference of more than X_ULONG_MAX / 2 as wraparound.
25268
25269 Note that these functions truncate serials to 32 bits before
25270 comparison. */
25271
25272static bool
25273x_is_serial_more_than (unsigned int a, unsigned int b)
25274{
25275 if (a > b)
25276 return true;
25277
25278 return (b - a > X_ULONG_MAX / 2);
25279}
25280
25281static bool
25282x_is_serial_more_than_or_equal_to (unsigned int a, unsigned int b)
25283{
25284 if (a >= b)
25285 return true;
25286
25287 return (b - a > X_ULONG_MAX / 2);
25288}
25289
25290static bool
25291x_is_serial_less_than (unsigned int a, unsigned int b)
25292{
25293 if (a < b)
25294 return true;
25295
25296 return (a - b > X_ULONG_MAX / 2);
25297}
25298
25299static bool
25300x_is_serial_less_than_or_equal_to (unsigned int a, unsigned int b)
25301{
25302 if (a <= b)
25303 return true;
25304
25305 return (a - b > X_ULONG_MAX / 2);
25306}
25307
24942static struct x_error_message_stack * 25308static struct x_error_message_stack *
24943x_find_error_handler (Display *dpy, XErrorEvent *event) 25309x_find_error_handler (Display *dpy, XErrorEvent *event)
24944{ 25310{
@@ -24948,8 +25314,8 @@ x_find_error_handler (Display *dpy, XErrorEvent *event)
24948 25314
24949 while (stack) 25315 while (stack)
24950 { 25316 {
24951 if (X_COMPARE_SERIALS (event->serial, >=, 25317 if (x_is_serial_more_than_or_equal_to (event->serial,
24952 stack->first_request) 25318 stack->first_request)
24953 && dpy == stack->dpy) 25319 && dpy == stack->dpy)
24954 return stack; 25320 return stack;
24955 25321
@@ -25052,11 +25418,11 @@ x_request_can_fail (struct x_display_info *dpyinfo,
25052 failable_requests < dpyinfo->next_failable_request; 25418 failable_requests < dpyinfo->next_failable_request;
25053 failable_requests++) 25419 failable_requests++)
25054 { 25420 {
25055 if (X_COMPARE_SERIALS (request, >=, 25421 if (x_is_serial_more_than_or_equal_to (request,
25056 failable_requests->start) 25422 failable_requests->start)
25057 && (!failable_requests->end 25423 && (!failable_requests->end
25058 || X_COMPARE_SERIALS (request, <=, 25424 || x_is_serial_less_than_or_equal_to (request,
25059 failable_requests->end))) 25425 failable_requests->end)))
25060 return failable_requests; 25426 return failable_requests;
25061 } 25427 }
25062 25428
@@ -25074,11 +25440,11 @@ x_clean_failable_requests (struct x_display_info *dpyinfo)
25074 25440
25075 for (first = dpyinfo->failable_requests; first < last; first++) 25441 for (first = dpyinfo->failable_requests; first < last; first++)
25076 { 25442 {
25077 if (X_COMPARE_SERIALS (first->start, >, 25443 if (x_is_serial_more_than (first->start,
25078 LastKnownRequestProcessed (dpyinfo->display)) 25444 LastKnownRequestProcessed (dpyinfo->display))
25079 || !first->end 25445 || !first->end
25080 || X_COMPARE_SERIALS (first->end, >, 25446 || x_is_serial_more_than (first->end,
25081 LastKnownRequestProcessed (dpyinfo->display))) 25447 LastKnownRequestProcessed (dpyinfo->display)))
25082 break; 25448 break;
25083 } 25449 }
25084 25450
@@ -25157,8 +25523,7 @@ x_stop_ignoring_errors (struct x_display_info *dpyinfo)
25157 /* Abort if no request was made since 25523 /* Abort if no request was made since
25158 `x_ignore_errors_for_next_request'. */ 25524 `x_ignore_errors_for_next_request'. */
25159 25525
25160 if (X_COMPARE_SERIALS (range->end, <, 25526 if (x_is_serial_less_than (range->end, range->start))
25161 range->start))
25162 emacs_abort (); 25527 emacs_abort ();
25163 25528
25164#ifdef HAVE_GTK3 25529#ifdef HAVE_GTK3
@@ -27347,11 +27712,10 @@ x_ewmh_activate_frame (struct frame *f)
27347 { 27712 {
27348 time = x_get_server_time (f); 27713 time = x_get_server_time (f);
27349 27714
27350 x_ignore_errors_for_next_request (dpyinfo); 27715 x_set_input_focus (FRAME_DISPLAY_INFO (f),
27351 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 27716 FRAME_OUTER_WINDOW (f),
27352 RevertToParent, time); 27717 time);
27353 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); 27718 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
27354 x_stop_ignoring_errors (dpyinfo);
27355 27719
27356 return; 27720 return;
27357 } 27721 }
@@ -27377,6 +27741,76 @@ x_get_focus_frame (struct frame *f)
27377 return lisp_focus; 27741 return lisp_focus;
27378} 27742}
27379 27743
27744/* Return the toplevel parent of F, if it is a child frame.
27745 Otherwise, return NULL. */
27746
27747static struct frame *
27748x_get_toplevel_parent (struct frame *f)
27749{
27750 struct frame *parent;
27751
27752 if (!FRAME_PARENT_FRAME (f))
27753 return NULL;
27754
27755 parent = FRAME_PARENT_FRAME (f);
27756
27757 while (FRAME_PARENT_FRAME (parent))
27758 parent = FRAME_PARENT_FRAME (parent);
27759
27760 return parent;
27761}
27762
27763static void
27764x_set_input_focus (struct x_display_info *dpyinfo, Window window,
27765 Time time)
27766{
27767#ifdef HAVE_XINPUT2
27768 struct xi_device_t *device;
27769#endif
27770
27771 /* Do the equivalent of XSetInputFocus with the specified window and
27772 time, but use the attachment to the device that Emacs has
27773 designated the client pointer on X Input Extension builds.
27774 Asynchronously trap errors around the generated XI_SetFocus or
27775 SetInputFocus request, in case the device has been destroyed or
27776 the window obscured.
27777
27778 The revert_to will be set to RevertToParent for generated
27779 SetInputFocus requests. */
27780
27781#ifdef HAVE_XINPUT2
27782 if (dpyinfo->supports_xi2
27783 && dpyinfo->client_pointer_device != -1)
27784 {
27785 device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
27786
27787 /* The device is a master pointer. Use its attachment, which
27788 should be the master keyboard. */
27789
27790 if (device)
27791 {
27792 eassert (device->use == XIMasterPointer);
27793
27794 x_ignore_errors_for_next_request (dpyinfo);
27795 XISetFocus (dpyinfo->display, device->attachment,
27796 /* Note that the input extension
27797 only supports RevertToParent-type
27798 behavior. */
27799 window, time);
27800 x_stop_ignoring_errors (dpyinfo);
27801
27802 return;
27803 }
27804 }
27805#endif
27806
27807 /* Otherwise, use the pointer device that the X server says is the
27808 client pointer. */
27809 x_ignore_errors_for_next_request (dpyinfo);
27810 XSetInputFocus (dpyinfo->display, window, RevertToParent, time);
27811 x_stop_ignoring_errors (dpyinfo);
27812}
27813
27380/* In certain situations, when the window manager follows a 27814/* In certain situations, when the window manager follows a
27381 click-to-focus policy, there seems to be no way around calling 27815 click-to-focus policy, there seems to be no way around calling
27382 XSetInputFocus to give another frame the input focus. 27816 XSetInputFocus to give another frame the input focus.
@@ -27402,6 +27836,18 @@ x_focus_frame (struct frame *f, bool noactivate)
27402 else 27836 else
27403 { 27837 {
27404 if (!noactivate 27838 if (!noactivate
27839 /* If F is override-redirect, use SetInputFocus instead.
27840 Override-redirect frames are not subject to window
27841 management. */
27842 && !FRAME_OVERRIDE_REDIRECT (f)
27843 /* If F is a child frame, use SetInputFocus instead. This
27844 may not work if its parent is not activated. */
27845 && !FRAME_PARENT_FRAME (f)
27846 /* If the focus is being transferred from a child frame to
27847 its toplevel parent, also use SetInputFocus. */
27848 && (!dpyinfo->x_focus_frame
27849 || (x_get_toplevel_parent (dpyinfo->x_focus_frame)
27850 != f))
27405 && x_wm_supports (f, dpyinfo->Xatom_net_active_window)) 27851 && x_wm_supports (f, dpyinfo->Xatom_net_active_window))
27406 { 27852 {
27407 /* When window manager activation is possible, use it 27853 /* When window manager activation is possible, use it
@@ -27413,8 +27859,6 @@ x_focus_frame (struct frame *f, bool noactivate)
27413 return; 27859 return;
27414 } 27860 }
27415 27861
27416 /* Ignore any BadMatch error this request might result in. */
27417 x_ignore_errors_for_next_request (dpyinfo);
27418 if (NILP (Vx_no_window_manager)) 27862 if (NILP (Vx_no_window_manager))
27419 { 27863 {
27420 /* Use the last user time. It is invalid to use CurrentTime 27864 /* Use the last user time. It is invalid to use CurrentTime
@@ -27432,15 +27876,19 @@ x_focus_frame (struct frame *f, bool noactivate)
27432 && !dpyinfo->x_focus_frame) 27876 && !dpyinfo->x_focus_frame)
27433 time = x_get_server_time (f); 27877 time = x_get_server_time (f);
27434 27878
27435 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 27879 /* Ignore any BadMatch error this request might result in.
27436 RevertToParent, time); 27880 A BadMatch error can occur if the window was obscured
27881 after the time of the last user interaction without
27882 changing the last-focus-change-time. */
27883 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
27884 time);
27437 } 27885 }
27438 else 27886 else
27439 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 27887 x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
27440 /* But when no window manager is in use, we 27888 /* But when no window manager is in use,
27441 don't care. */ 27889 respecting the ICCCM doesn't really
27442 RevertToParent, CurrentTime); 27890 matter. */
27443 x_stop_ignoring_errors (dpyinfo); 27891 CurrentTime);
27444 } 27892 }
27445} 27893}
27446 27894
@@ -28912,10 +29360,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
28912#endif 29360#endif
28913 int i; 29361 int i;
28914 29362
29363#if defined HAVE_XFIXES && defined USE_XCB
28915 USE_SAFE_ALLOCA; 29364 USE_SAFE_ALLOCA;
28916 29365#endif
28917 /* Avoid warnings when SAFE_ALLOCA is not actually used. */
28918 ((void) SAFE_ALLOCA (0));
28919 29366
28920 block_input (); 29367 block_input ();
28921 29368
@@ -29069,7 +29516,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29069 29516
29070 unblock_input (); 29517 unblock_input ();
29071 29518
29519#if defined HAVE_XFIXES && defined USE_XCB
29072 SAFE_FREE (); 29520 SAFE_FREE ();
29521#endif
29073 return 0; 29522 return 0;
29074 } 29523 }
29075 29524
@@ -29089,7 +29538,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29089 29538
29090 unblock_input (); 29539 unblock_input ();
29091 29540
29541#if defined HAVE_XFIXES && defined USE_XCB
29092 SAFE_FREE (); 29542 SAFE_FREE ();
29543#endif
29093 return 0; 29544 return 0;
29094 } 29545 }
29095#endif 29546#endif
@@ -29559,11 +30010,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29559 xi_select_hierarchy_events (dpyinfo); 30010 xi_select_hierarchy_events (dpyinfo);
29560#endif 30011#endif
29561 30012
30013 dpyinfo->xi2_version = minor;
29562 x_cache_xi_devices (dpyinfo); 30014 x_cache_xi_devices (dpyinfo);
29563 } 30015 }
29564 } 30016 }
29565
29566 dpyinfo->xi2_version = minor;
29567 skip_xi_setup: 30017 skip_xi_setup:
29568 ; 30018 ;
29569#endif 30019#endif
@@ -29778,21 +30228,30 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29778 { 30228 {
29779 XrmValue d, fr, to; 30229 XrmValue d, fr, to;
29780 Font font; 30230 Font font;
30231 XFontStruct *query_result;
29781 30232
29782 dpy = dpyinfo->display; 30233 dpy = dpyinfo->display;
29783 d.addr = (XPointer)&dpy; 30234 d.addr = (XPointer) &dpy;
29784 d.size = sizeof (Display *); 30235 d.size = sizeof (Display *);
29785 fr.addr = (char *) XtDefaultFont; 30236 fr.addr = (char *) XtDefaultFont;
29786 fr.size = sizeof (XtDefaultFont); 30237 fr.size = sizeof (XtDefaultFont);
29787 to.size = sizeof (Font *); 30238 to.size = sizeof (Font *);
29788 to.addr = (XPointer)&font; 30239 to.addr = (XPointer) &font;
29789 x_catch_errors (dpy); 30240 x_catch_errors (dpy);
29790 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL)) 30241 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
29791 emacs_abort (); 30242 emacs_abort ();
29792 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font)) 30243 query_result = XQueryFont (dpy, font);
30244
30245 /* Set the dialog font to some fallback (here, 9x15) if the font
30246 specified is invalid. */
30247 if (x_had_errors_p (dpy) || !font)
29793 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15"); 30248 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
29794 /* Do not free XFontStruct returned by the above call to XQueryFont. 30249
29795 This leads to X protocol errors at XtCloseDisplay (Bug#18403). */ 30250 /* Do not destroy the font struct returned above with XFreeFont;
30251 that also destroys the font, leading to X protocol errors at
30252 XtCloseDisplay. Just free the font info structure.
30253 (Bug#18403) */
30254 XFreeFontInfo (NULL, query_result, 1);
29796 x_uncatch_errors (); 30255 x_uncatch_errors ();
29797 } 30256 }
29798#endif 30257#endif
@@ -29966,7 +30425,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29966 30425
29967 unblock_input (); 30426 unblock_input ();
29968 30427
30428#if defined HAVE_XFIXES && defined USE_XCB
29969 SAFE_FREE (); 30429 SAFE_FREE ();
30430#endif
29970 return dpyinfo; 30431 return dpyinfo;
29971} 30432}
29972 30433
@@ -30846,6 +31307,7 @@ With MS Windows, Haiku windowing or Nextstep, the value is t. */);
30846 DEFSYM (Qimitate_pager, "imitate-pager"); 31307 DEFSYM (Qimitate_pager, "imitate-pager");
30847 DEFSYM (Qnewer_time, "newer-time"); 31308 DEFSYM (Qnewer_time, "newer-time");
30848 DEFSYM (Qraise_and_focus, "raise-and-focus"); 31309 DEFSYM (Qraise_and_focus, "raise-and-focus");
31310 DEFSYM (Qreally_fast, "really-fast");
30849 31311
30850 DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym, 31312 DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym,
30851 doc: /* Which keys Emacs uses for the ctrl modifier. 31313 doc: /* Which keys Emacs uses for the ctrl modifier.
@@ -31125,4 +31587,19 @@ not bypass window manager focus stealing prevention):
31125 - The symbol `raise-and-focus', which means to raise the window and 31587 - The symbol `raise-and-focus', which means to raise the window and
31126 focus it manually. */); 31588 focus it manually. */);
31127 Vx_allow_focus_stealing = Qnewer_time; 31589 Vx_allow_focus_stealing = Qnewer_time;
31590
31591 DEFVAR_LISP ("x-use-fast-mouse-position", Vx_use_fast_mouse_position,
31592 doc: /* How to make `mouse-position' faster.
31593
31594`mouse-position' and `mouse-pixel-position' default to querying the X
31595server for the window under the mouse pointer. This results in
31596accurate results, but is also very slow when the X connection has
31597moderate to high latency. Setting this variable to a non-nil value
31598makes Emacs query only for the position of the pointer, which is
31599usually faster. Doing so improves the performance of dragging to
31600select text over slow X connections.
31601
31602If that is still too slow, setting this variable to the symbol
31603`really-fast' will make Emacs return only cached values. */);
31604 Vx_use_fast_mouse_position = Qnil;
31128} 31605}
diff --git a/src/xterm.h b/src/xterm.h
index 1124dcceb4a..c36920081d3 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -580,7 +580,9 @@ struct x_display_info
580 Time last_user_time; 580 Time last_user_time;
581 581
582 /* Position where the mouse was last time we reported a motion. 582 /* Position where the mouse was last time we reported a motion.
583 This is a position on last_mouse_motion_frame. */ 583 This is a position on last_mouse_motion_frame. It is used in
584 some situations to report the mouse position as well: see
585 XTmouse_position. */
584 int last_mouse_motion_x; 586 int last_mouse_motion_x;
585 int last_mouse_motion_y; 587 int last_mouse_motion_y;
586 588
@@ -1605,22 +1607,15 @@ SELECTION_EVENT_DISPLAY (struct selection_input_event *ev)
1605 1607
1606extern void x_free_gcs (struct frame *); 1608extern void x_free_gcs (struct frame *);
1607extern void x_relative_mouse_position (struct frame *, int *, int *); 1609extern void x_relative_mouse_position (struct frame *, int *, int *);
1608extern void x_real_pos_and_offsets (struct frame *f, 1610extern void x_real_pos_and_offsets (struct frame *, int *, int *, int *,
1609 int *left_offset_x, 1611 int *, int *, int *, int *, int *,
1610 int *right_offset_x, 1612 int *);
1611 int *top_offset_y, 1613extern void x_default_font_parameter (struct frame *, Lisp_Object);
1612 int *bottom_offset_y,
1613 int *x_pixels_diff,
1614 int *y_pixels_diff,
1615 int *xptr,
1616 int *yptr,
1617 int *outer_border);
1618extern void x_default_font_parameter (struct frame* f, Lisp_Object parms);
1619 1614
1620/* From xrdb.c. */ 1615/* From xrdb.c. */
1621 1616
1622XrmDatabase x_load_resources (Display *, const char *, const char *, 1617extern XrmDatabase x_load_resources (Display *, const char *, const char *,
1623 const char *); 1618 const char *);
1624extern const char *x_get_string_resource (void *, const char *, const char *); 1619extern const char *x_get_string_resource (void *, const char *, const char *);
1625 1620
1626/* Defined in xterm.c */ 1621/* Defined in xterm.c */