diff options
| author | Gregory Heytings | 2022-11-24 14:21:30 +0100 |
|---|---|---|
| committer | Gregory Heytings | 2022-11-24 14:21:30 +0100 |
| commit | ba9315b1641b483f2bf843c38dcdba0cd1643a55 (patch) | |
| tree | d119cae86c7386db66be72972d90f6c83215974d /src | |
| parent | aef803d6c3d61004f15d0bc82fa7bf9952302312 (diff) | |
| parent | a3b654e069e563b0a2a6335ec310ada51400ac09 (diff) | |
| download | emacs-ba9315b1641b483f2bf843c38dcdba0cd1643a55.tar.gz emacs-ba9315b1641b483f2bf843c38dcdba0cd1643a55.zip | |
Merge master into feature/improved-locked-narrowing.
Diffstat (limited to 'src')
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 | ||
| 7904 | 2005-07-18 Ken Raeburn <raeburn@gnu.org> | 7904 | 2005-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 @@ | |||
| 7503 | 2010-05-28 Kenichi Handa <handa@m17n.org> | 7503 | 2010-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 | ||
| 1815 | 2012-12-22 Martin Rudalics <rudalics@gmx.at> | 1815 | 2012-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 | ||
| 14137 | 2011-12-05 Kazuhiro Ito <kzhr@d1.dion.ne.jp> (tiny change) | 14137 | 2011-12-05 Kazuhiro Ito <kzhr@d1.dion.ne.jp> (tiny change) |
| 14138 | 14138 | ||
| @@ -19967,7 +19967,7 @@ | |||
| 19967 | 2011-05-05 Eli Zaretskii <eliz@gnu.org> | 19967 | 2011-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 | ||
| 19972 | 2011-05-05 Chong Yidong <cyd@stupidchicken.com> | 19972 | 2011-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 | ||
| 1482 | 2015-01-12 Paul Eggert <eggert@cs.ucla.edu> | 1482 | 2015-01-12 Paul Eggert <eggert@cs.ucla.edu> |
| @@ -7498,7 +7498,7 @@ | |||
| 7498 | 2014-04-16 Eli Zaretskii <eliz@gnu.org> | 7498 | 2014-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 | ||
| 7504 | 2014-04-16 Paul Eggert <eggert@cs.ucla.edu> | 7504 | 2014-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 @@ | |||
| 12566 | 2013-09-16 Dmitry Antipov <dmantipov@yandex.ru> | 12566 | 2013-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 | ||
| 2317 | 1995-02-15 Paul Reilly <pmr@geech.gnu.ai.mit.edu> | 2317 | 1995-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 | ||
| 2322 | 1995-02-15 Richard Stallman <rms@pogo.gnu.ai.mit.edu> | 2322 | 1995-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 | ||
| 2226 | 1996-02-08 Eli Zaretskii <eliz@is.elta.co.il> | 2226 | 1996-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 | ||
| 2231 | 1996-02-07 Richard Stallman <rms@mole.gnu.ai.mit.edu> | 2231 | 1996-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 | ||
| 1277 | 1999-11-01 Gerd Moellmann <gerd@gnu.org> | 1277 | 1999-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 | ||
| 3161 | 1999-08-25 Alexandre Oliva <oliva@dcc.unicamp.br> | 3161 | 1999-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) | |||
| 6508 | static void | 6503 | static void |
| 6509 | mark_overlay (struct Lisp_Overlay *ov) | 6504 | mark_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. | |||
| 7780 | Garbage collection happens automatically only when `eval' is called. | 7775 | Garbage collection happens automatically only when `eval' is called. |
| 7781 | 7776 | ||
| 7782 | By binding this temporarily to a large number, you can effectively | 7777 | By binding this temporarily to a large number, you can effectively |
| 7783 | prevent garbage collection during a part of the program. | 7778 | prevent garbage collection during a part of the program. But be |
| 7779 | sure to get back to the normal value soon enough, to avoid system-wide | ||
| 7780 | memory pressure, and never use a too-high value for prolonged periods | ||
| 7781 | of time. | ||
| 7784 | See also `gc-cons-percentage'. */); | 7782 | See 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. |
| 7788 | Garbage collection can happen automatically once this portion of the heap | 7786 | Garbage collection can happen automatically once this portion of the heap |
| 7789 | has been allocated since the last garbage collection. | 7787 | has been allocated since the last garbage collection. |
| 7788 | |||
| 7789 | By binding this temporarily to a large number, you can effectively | ||
| 7790 | prevent garbage collection during a part of the program. But be | ||
| 7791 | sure to get back to the normal value soon enough, to avoid system-wide | ||
| 7792 | memory pressure, and never use a too-high value for prolonged periods | ||
| 7793 | of time. | ||
| 7794 | |||
| 7790 | If this portion is smaller than `gc-cons-threshold', this is ignored. */); | 7795 | If 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 | ||
| 3456 | void | 3445 | void |
| 3457 | adjust_overlays_for_insert (ptrdiff_t pos, ptrdiff_t length) | 3446 | adjust_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 | |||
| 3464 | static void | ||
| 3465 | adjust_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 | ||
| 3466 | void | 3490 | void |
| 3467 | adjust_overlays_for_delete (ptrdiff_t pos, ptrdiff_t length) | 3491 | adjust_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 | ||
| 3791 | Empty overlays are included in the result if they are located at BEG, | 3825 | Empty overlays are included in the result if they are located at BEG, |
| 3792 | between BEG and END, or at END provided END denotes the position at the | 3826 | between BEG and END, or at END provided END denotes the position at the |
| 3793 | end of the accessible part of the buffer. */) | 3827 | end of the accessible part of the buffer. |
| 3828 | |||
| 3829 | The 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. */ | ||
| 4085 | void | ||
| 4086 | evaporate_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); | |||
| 1170 | extern void delete_all_overlays (struct buffer *); | 1170 | extern void delete_all_overlays (struct buffer *); |
| 1171 | extern void reset_buffer (struct buffer *); | 1171 | extern void reset_buffer (struct buffer *); |
| 1172 | extern void compact_buffer (struct buffer *); | 1172 | extern void compact_buffer (struct buffer *); |
| 1173 | extern void evaporate_overlays (ptrdiff_t); | ||
| 1174 | extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); | 1173 | extern ptrdiff_t overlays_at (ptrdiff_t, bool, Lisp_Object **, ptrdiff_t *, ptrdiff_t *); |
| 1175 | extern ptrdiff_t overlays_in (ptrdiff_t, ptrdiff_t, bool, Lisp_Object **, | 1174 | extern 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. */ |
| 5610 | DEFUN ("native-elisp-load", Fnative_elisp_load, Snative_elisp_load, 1, 2, 0, | 5610 | DEFUN ("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. |
| 5612 | LATE_LOAD has to be non-nil when loading for deferred compilation. */) | 5612 | LATE-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); | |||
| 3495 | extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *, | 3495 | extern 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); |
| 3497 | extern void display_tty_menu_item (const char *, int, int, int, int, bool); | 3497 | extern void display_tty_menu_item (const char *, int, int, int, int, bool); |
| 3498 | 3498 | extern 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 * | |||
| 561 | allocate_module_function (void) | 561 | allocate_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' | |||
| 1329 | expression. | 1329 | expression. |
| 1330 | 1330 | ||
| 1331 | The special handler (:success BODY...) is invoked if BODYFORM terminated | 1331 | The special handler (:success BODY...) is invoked if BODYFORM terminated |
| 1332 | without signalling an error. BODY is then evaluated with VAR bound to | 1332 | without signaling an error. BODY is then evaluated with VAR bound to |
| 1333 | the value returned by BODYFORM. | 1333 | the value returned by BODYFORM. |
| 1334 | 1334 | ||
| 1335 | See also the function `signal' for more info. | 1335 | See 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 | ||
| 4124 | void | 4130 | void |
| 4125 | gui_set_frame_parameters (struct frame *f, Lisp_Object alist) | 4131 | gui_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 | ||
| 4426 | void | ||
| 4427 | gui_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 | |||
| 5967 | DEFUN ("reconsider-frame-fonts", Freconsider_frame_fonts, | ||
| 5968 | Sreconsider_frame_fonts, 1, 1, 0, | ||
| 5969 | doc: /* Recreate FRAME's default font using updated font parameters. | ||
| 5970 | Signal an error if FRAME is not a window system frame. This should be | ||
| 5971 | called after a `config-changed' event is received, signaling that the | ||
| 5972 | parameters (such as pixel density) used by the system to open fonts | ||
| 5973 | have 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 | ||
| 1673 | extern void gui_set_frame_parameters_1 (struct frame *, Lisp_Object, bool); | ||
| 1673 | extern void gui_set_frame_parameters (struct frame *, Lisp_Object); | 1674 | extern void gui_set_frame_parameters (struct frame *, Lisp_Object); |
| 1674 | extern void gui_set_fullscreen (struct frame *, Lisp_Object, Lisp_Object); | 1675 | extern void gui_set_fullscreen (struct frame *, Lisp_Object, Lisp_Object); |
| 1675 | extern void gui_set_line_spacing (struct frame *, Lisp_Object, Lisp_Object); | 1676 | extern 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 | |||
| 763 | void | ||
| 764 | ftcrfont_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 | |||
| 758 | static void | 794 | static void |
| 759 | syms_of_ftcrfont_for_pdumper (void) | 795 | syms_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 | |||
| 89 | extern 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) | |||
| 175 | void | 175 | void |
| 176 | haiku_change_tab_bar_height (struct frame *f, int height) | 176 | haiku_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. |
| 1263 | Otherwise, an error will be signalled if adding a file reference to a | 1263 | Otherwise, an error will be signaled if adding a file reference to a |
| 1264 | system message failed. */); | 1264 | system 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, | |||
| 3238 | static void | 3241 | static void |
| 3239 | x_destroy_x_image (XImage *ximg) | 3242 | x_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 | |||
| 6224 | image_from_emacs_colors (struct frame *f, struct image *img, Emacs_Color *colors) | 6228 | image_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 | ||
| 134 | typedef uintptr_t nodeptr_and_flag; | ||
| 135 | |||
| 136 | static inline nodeptr_and_flag | ||
| 137 | make_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 | |||
| 145 | static inline struct itree_node * | ||
| 146 | nav_nodeptr (nodeptr_and_flag nav) | ||
| 147 | { | ||
| 148 | return (struct itree_node *) (nav & (~(uintptr_t)1)); | ||
| 149 | } | ||
| 150 | |||
| 151 | static inline bool | ||
| 152 | nav_flag (nodeptr_and_flag nav) | ||
| 153 | { | ||
| 154 | return (bool) (nav & 1); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* Simple dynamic array. */ | 134 | /* Simple dynamic array. */ |
| 158 | struct interval_stack | 135 | struct 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 | ||
| 167 | static struct interval_stack* | 144 | static struct itree_stack* |
| 168 | interval_stack_create (intmax_t initial_size) | 145 | itree_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 | ||
| 177 | static void | 154 | static void |
| 178 | interval_stack_destroy (struct interval_stack *stack) | 155 | itree_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 | ||
| 187 | static void | ||
| 188 | interval_stack_clear (struct interval_stack *stack) | ||
| 189 | { | ||
| 190 | stack->length = 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static inline void | 164 | static inline void |
| 194 | interval_stack_ensure_space (struct interval_stack *stack, intmax_t nelements) | 165 | itree_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 | ||
| 206 | static inline void | 177 | static inline void |
| 207 | interval_stack_push_flagged (struct interval_stack *stack, | 178 | itree_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 | ||
| 224 | static inline void | 187 | static inline struct itree_node * |
| 225 | interval_stack_push (struct interval_stack *stack, struct itree_node *node) | 188 | itree_stack_pop (struct itree_stack *stack) |
| 226 | { | ||
| 227 | interval_stack_push_flagged (stack, node, false); | ||
| 228 | } | ||
| 229 | |||
| 230 | static inline nodeptr_and_flag | ||
| 231 | interval_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. */ | ||
| 242 | struct 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. */ | ||
| 261 | static struct itree_iterator *iter; | ||
| 262 | |||
| 263 | static int | 198 | static int |
| 264 | interval_tree_max_height (const struct itree_tree *tree) | 199 | itree_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 | |||
| 271 | static struct itree_iterator * | ||
| 272 | itree_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 | |||
| 290 | static void | ||
| 291 | itree_init (void) | ||
| 292 | { | ||
| 293 | iter = itree_iterator_create (NULL); | ||
| 294 | } | ||
| 295 | |||
| 296 | struct check_subtree_result | 204 | struct 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 | ||
| 431 | static void | 339 | static void |
| 432 | interval_tree_update_limit (struct itree_node *node) | 340 | itree_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 | ||
| 446 | static void | 354 | static void |
| 447 | interval_tree_inherit_offset (uintmax_t otick, struct itree_node *node) | 355 | itree_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 | ||
| 483 | static void | 391 | static void |
| 484 | interval_tree_propagate_limit (struct itree_node *node) | 392 | itree_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 | ||
| 504 | static struct itree_node* | 412 | static struct itree_node* |
| 505 | interval_tree_validate (struct itree_tree *tree, struct itree_node *node) | 413 | itree_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 | |||
| 541 | itree_node_begin (struct itree_tree *tree, | 449 | itree_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 | |||
| 551 | itree_node_end (struct itree_tree *tree, | 459 | itree_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 | ||
| 560 | struct itree_tree * | 468 | struct itree_tree * |
| 561 | itree_create (void) | 469 | itree_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 | ||
| 586 | static void | 489 | static void |
| 587 | interval_tree_init (struct interval_tree *tree) | 490 | itree_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 | |||
| 596 | itree_destroy (struct itree_tree *tree) | 498 | itree_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 | ||
| 614 | static void | 514 | static void |
| 615 | interval_tree_rotate_left (struct itree_tree *tree, | 515 | itree_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 | ||
| 657 | static void | 557 | static void |
| 658 | interval_tree_rotate_right (struct itree_tree *tree, | 558 | itree_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 | ||
| 696 | static void | 596 | static void |
| 697 | interval_tree_insert_fix (struct itree_tree *tree, | 597 | itree_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 | ||
| 775 | static void | 675 | static void |
| 776 | interval_tree_insert (struct itree_tree *tree, struct itree_node *node) | 676 | itree_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 | ||
| 868 | static bool | 766 | static bool |
| 869 | interval_tree_contains (struct itree_tree *tree, struct itree_node *node) | 767 | itree_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 | ||
| 892 | static struct itree_node* | 787 | static struct itree_node* |
| 893 | interval_tree_subtree_min (uintmax_t otick, struct itree_node *node) | 788 | itree_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 | ||
| 907 | static void | 802 | static void |
| 908 | interval_tree_remove_fix (struct itree_tree *tree, | 803 | itree_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`. */ |
| 1025 | static void | 920 | static void |
| 1026 | interval_tree_replace_child (struct itree_tree *tree, | 921 | itree_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`. */ |
| 1051 | static void | 946 | static void |
| 1052 | interval_tree_transplant (struct itree_tree *tree, | 947 | itree_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, | |||
| 1068 | struct itree_node* | 963 | struct itree_node* |
| 1069 | itree_remove (struct itree_tree *tree, struct itree_node *node) | 964 | itree_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 | ||
| 1140 | bool | ||
| 1141 | itree_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 | |||
| 1149 | struct itree_iterator * | ||
| 1150 | itree_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 | |||
| 1179 | void | ||
| 1180 | itree_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 | ||
| 1195 | void | 1047 | void |
| 1196 | itree_insert_gap (struct itree_tree *tree, | 1048 | itree_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 | ||
| 1279 | void | 1140 | void |
| 1280 | itree_delete_gap (struct itree_tree *tree, | 1141 | itree_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 | ||
| 1341 | static inline bool | 1201 | static inline bool |
| 1342 | interval_node_intersects (const struct itree_node *node, | 1202 | itree_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 | ||
| 1352 | struct itree_node * | 1211 | Note that this should return all the nodes that we need to traverse |
| 1353 | itree_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): | 1221 | static struct itree_node * |
| 1361 | We keep a "workstack" of nodes we need to consider. This stack | 1222 | itree_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); | 1337 | static struct itree_node * |
| 1383 | eassert (itree_limit_is_stable (node)); | 1338 | itree_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 | |||
| 1382 | struct itree_iterator * | ||
| 1383 | itree_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 | ||
| 1402 | struct itree_node * | ||
| 1403 | itree_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 | |||
| 1424 | itree_iterator_narrow (struct itree_iterator *g, | 1420 | itree_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 | ||
| 109 | extern void itree_node_init (struct itree_node *, bool, bool, Lisp_Object); | 110 | extern 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); |
| 120 | extern struct itree_node *itree_remove (struct itree_tree *, | 121 | extern struct itree_node *itree_remove (struct itree_tree *, |
| 121 | struct itree_node *); | 122 | struct itree_node *); |
| 122 | extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); | 123 | extern void itree_insert_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t, bool); |
| 123 | extern void itree_delete_gap (struct itree_tree *, ptrdiff_t, ptrdiff_t); | 124 | extern 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. */ |
| 127 | extern bool itree_iterator_busy_p (void); | 128 | extern struct itree_iterator *itree_iterator_start (struct itree_iterator *, |
| 128 | extern 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); | ||
| 133 | extern void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t, | 133 | extern void itree_iterator_narrow (struct itree_iterator *, ptrdiff_t, |
| 134 | ptrdiff_t); | 134 | ptrdiff_t); |
| 135 | extern void itree_iterator_finish (struct itree_iterator *); | ||
| 136 | extern struct itree_node *itree_iterator_next (struct itree_iterator *); | 135 | extern struct itree_node *itree_iterator_next (struct itree_iterator *); |
| 137 | 136 | ||
| 137 | /* State used when iterating interval. */ | ||
| 138 | struct 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, | ||
| 510 | str); | ||
| 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 | |||
| 5728 | static bool | ||
| 5729 | coords_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); | |||
| 4690 | extern bool mouse_face_overlay_overlaps (Lisp_Object); | 4690 | extern bool mouse_face_overlay_overlaps (Lisp_Object); |
| 4691 | extern Lisp_Object disable_line_numbers_overlay_at_eob (void); | 4691 | extern Lisp_Object disable_line_numbers_overlay_at_eob (void); |
| 4692 | extern AVOID nsberror (Lisp_Object); | 4692 | extern AVOID nsberror (Lisp_Object); |
| 4693 | extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t); | 4693 | extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t, bool); |
| 4694 | extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); | 4694 | extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t); |
| 4695 | extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t); | 4695 | extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t); |
| 4696 | extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool, | 4696 | extern 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. */ |
| 4917 | struct Lisp_Process; | 4917 | struct Lisp_Process; |
| 4918 | extern void child_signal_init (void); | ||
| 4918 | extern void kill_buffer_processes (Lisp_Object); | 4919 | extern void kill_buffer_processes (Lisp_Object); |
| 4919 | extern int wait_reading_process_output (intmax_t, int, int, bool, Lisp_Object, | 4920 | extern 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. | |||
| 5619 | When the regular expression matches, the file is considered to be safe | 5623 | When the regular expression matches, the file is considered to be safe |
| 5620 | to load. */); | 5624 | to 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) | |||
| 632 | void | 632 | void |
| 633 | ns_change_tab_bar_height (struct frame *f, int height) | 633 | ns_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 | ||
| 7059 | static Lisp_Object | ||
| 7060 | ns_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 | |||
| 7072 | static Lisp_Object | ||
| 7073 | ns_in_echo_area_2 (enum nonlocal_exit exit, Lisp_Object error) | ||
| 7074 | { | ||
| 7075 | return Qnil; | ||
| 7076 | } | ||
| 7077 | |||
| 7078 | static bool | ||
| 7079 | ns_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 | |||
| 2137 | dump_interval_node (struct dump_context *ctx, struct itree_node *node, | 2137 | dump_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, | |||
| 2179 | static dump_off | 2179 | static dump_off |
| 2180 | dump_overlay (struct dump_context *ctx, const struct Lisp_Overlay *overlay) | 2180 | dump_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, | |||
| 2748 | static dump_off | 2748 | static dump_off |
| 2749 | dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) | 2749 | dump_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) | |||
| 473 | void | 473 | void |
| 474 | pgtk_change_tab_bar_height (struct frame *f, int height) | 474 | pgtk_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 | ||
| 715 | void | 715 | void |
| 716 | pgtk_iconify_frame (struct frame *f) | 716 | pgtk_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 | ||
| 753 | static gboolean | 755 | static 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) | |||
| 4516 | void | 4518 | void |
| 4517 | pgtk_focus_frame (struct frame *f, bool noactivate) | 4519 | pgtk_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 | ||
| 4531 | static void | 4546 | static void |
| @@ -5142,13 +5157,15 @@ static gboolean | |||
| 5142 | key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) | 5157 | key_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 | ||
| 5387 | static struct pgtk_display_info * | ||
| 5388 | pgtk_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 | |||
| 5364 | static gboolean | 5401 | static gboolean |
| 5365 | key_release_event (GtkWidget *widget, | 5402 | key_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 | |||
| 6654 | static void | ||
| 6655 | pgtk_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. */ |
| 294 | static int child_signal_write_fd = -1; | 294 | static int child_signal_write_fd = -1; |
| 295 | static void child_signal_init (void); | ||
| 296 | #ifndef WINDOWSNT | 295 | #ifndef WINDOWSNT |
| 297 | static void child_signal_read (int, void *); | 296 | static 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 | ||
| 7326 | static void | 7325 | void |
| 7327 | child_signal_init (void) | 7326 | child_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 | ||
| 2826 | DEFUN ("match-data", Fmatch_data, Smatch_data, 0, 3, 0, | 2824 | DEFUN ("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. |
| 2828 | Element 2N is `(match-beginning N)'; element 2N + 1 is `(match-end N)'. | 2826 | Element 2N of the returned list is the position of the beginning of the |
| 2829 | All the elements are markers or nil (nil if the Nth pair didn't match) | 2827 | match of the Nth subexpression; it corresponds to `(match-beginning N)'; |
| 2830 | if the last match was on a buffer; integers or nil if a string was matched. | 2828 | element 2N + 1 is the position of the end of the match of the Nth |
| 2831 | Use `set-match-data' to reinstate the data in this list. | 2829 | subexpression; it corresponds to `(match-end N)'. See `match-beginning' |
| 2830 | and `match-end'. | ||
| 2831 | If the last search was on a buffer, all the elements are by default | ||
| 2832 | markers or nil (nil when the Nth pair didn't match); they are integers | ||
| 2833 | or nil if the search was on a string. But if the optional argument | ||
| 2834 | INTEGERS is non-nil, the elements that represent buffer positions are | ||
| 2835 | always integers, not markers, and (if the search was on a buffer) the | ||
| 2836 | buffer itself is appended to the list as one additional element. | ||
| 2837 | |||
| 2838 | Use `set-match-data' to reinstate the match data from the elements of | ||
| 2839 | this list. | ||
| 2832 | 2840 | ||
| 2833 | Note that non-matching optional groups at the end of the regexp are | 2841 | Note that non-matching optional groups at the end of the regexp are |
| 2834 | elided instead of being represented with two `nil's each. For instance: | 2842 | elided 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 | ||
| 2841 | If INTEGERS (the optional first argument) is non-nil, always use | 2849 | If REUSE is a list, store the value in REUSE by destructively modifying it. |
| 2842 | integers (rather than markers) to represent buffer positions. In | 2850 | If REUSE is long enough to hold all the values, its length remains the |
| 2843 | this case, and if the last match was in a buffer, the buffer will get | 2851 | same, and any unused elements are set to nil. If REUSE is not long |
| 2844 | stored as one additional element at the end of the list. | 2852 | enough, it is extended. Note that if REUSE is long enough and INTEGERS |
| 2845 | 2853 | is non-nil, no consing is done to make the return value; this minimizes GC. | |
| 2846 | If REUSE is a list, reuse it as part of the value. If REUSE is long | ||
| 2847 | enough to hold all the values, and if INTEGERS is non-nil, no consing | ||
| 2848 | is done. | ||
| 2849 | 2854 | ||
| 2850 | If optional third arg RESEAT is non-nil, any previous markers on the | 2855 | If optional third argument RESEAT is non-nil, any previous markers on the |
| 2851 | REUSE list will be modified to point to nowhere. | 2856 | REUSE list will be modified to point to nowhere. |
| 2852 | 2857 | ||
| 2853 | Return value is undefined if the last search failed. */) | 2858 | Return 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)); | |||
| 52 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); | 52 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); |
| 53 | DEF_DLL_FN (SQLITE_API int, sqlite3_extended_errcode, (sqlite3*)); | 53 | DEF_DLL_FN (SQLITE_API int, sqlite3_extended_errcode, (sqlite3*)); |
| 54 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); | 54 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); |
| 55 | #if SQLITE_VERSION_NUMBER >= 3007015 | ||
| 55 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); | 56 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); |
| 57 | #endif | ||
| 56 | DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); | 58 | DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); |
| 57 | DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); | 59 | DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); |
| 58 | DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); | 60 | DEF_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) | |||
| 428 | static Lisp_Object | 436 | static Lisp_Object |
| 429 | sqlite_prepare_errdata (int code, sqlite3 *sdb) | 437 | sqlite_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 | ||
| 440 | DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, | 462 | DEFUN ("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) | |||
| 1717 | void | 1717 | void |
| 1718 | w32_change_tab_bar_height (struct frame *f, int height) | 1718 | w32_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 | ||
| 2333 | static struct glyph * | 2333 | struct glyph * |
| 2334 | x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos, | 2334 | x_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) | |||
| 33597 | bool | 33611 | bool |
| 33598 | cursor_in_mouse_face_p (struct window *w) | 33612 | cursor_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) | |||
| 1750 | void | 1758 | void |
| 1751 | x_change_tab_bar_height (struct frame *f, int height) | 1759 | x_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 | ||
| 965 | static bool | 972 | static bool |
| 966 | x_convert_selection (Lisp_Object selection_symbol, | 973 | x_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 | ||
| 770 | static bool | 771 | static bool |
| 771 | read_settings (Display_Info *dpyinfo, struct xsettings *settings) | 772 | read_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 | ||
| 913 | struct x_selection_request_event *pending_selection_requests; | 913 | struct 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 | |||
| 920 | struct x_atom_ref | 915 | struct 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 *); | |||
| 1139 | static struct frame *x_tooltip_window_to_frame (struct x_display_info *, | 1134 | static struct frame *x_tooltip_window_to_frame (struct x_display_info *, |
| 1140 | Window, bool *); | 1135 | Window, bool *); |
| 1141 | static Window x_get_window_below (Display *, Window, int, int, int *, int *); | 1136 | static Window x_get_window_below (Display *, Window, int, int, int *, int *); |
| 1137 | static 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 |
| 1144 | static void x_scroll_bar_redraw (struct scroll_bar *); | 1140 | static 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 |
| 5251 | static | 5249 | static |
| @@ -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 | |||
| 5268 | static unsigned int | ||
| 5269 | xi_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. */ |
| 5267 | static void | 5276 | static void |
| 5268 | x_free_xi_devices (struct x_display_info *dpyinfo) | 5277 | x_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 | |||
| 5304 | struct xi_known_valuator | 5314 | struct 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 | |||
| 5351 | static void | ||
| 5352 | xi_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 | ||
| 5317 | static void | 5368 | static void |
| 5318 | xi_populate_device_from_info (struct xi_device_t *xi_device, | 5369 | xi_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 | |||
| 5610 | xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, | 5725 | xi_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 | |
| 11420 | static bool | 11540 | static bool |
| 11421 | x_probe_xfixes_extension (struct x_display_info *dpyinfo) | 11541 | x_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 | ||
| 11536 | static void | 11660 | static void |
| 11537 | x_focus_changed (int type, int state, struct x_display_info *dpyinfo, struct frame *frame, | 11661 | x_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 | 13147 | static bool |
| 13023 | changed, and update its information with the data in EVENT. */ | 13148 | xi_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 | ||
| 13025 | static void | 13168 | static void |
| 13026 | xi_handle_device_changed (struct x_display_info *dpyinfo, | 13169 | xi_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 | |||
| 13254 | static void | ||
| 13255 | xi_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 | |||
| 14268 | static void | ||
| 14269 | x_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, ©.xkey.state); | 23309 | xi_convert_button_state (&xev->buttons, ©.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. */ |
| 24940 | int x_error_message_count; | 25264 | int 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 | |||
| 25272 | static bool | ||
| 25273 | x_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 | |||
| 25281 | static bool | ||
| 25282 | x_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 | |||
| 25290 | static bool | ||
| 25291 | x_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 | |||
| 25299 | static bool | ||
| 25300 | x_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 | |||
| 24942 | static struct x_error_message_stack * | 25308 | static struct x_error_message_stack * |
| 24943 | x_find_error_handler (Display *dpy, XErrorEvent *event) | 25309 | x_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 | |||
| 27747 | static struct frame * | ||
| 27748 | x_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 | |||
| 27763 | static void | ||
| 27764 | x_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 | ||
| 31595 | server for the window under the mouse pointer. This results in | ||
| 31596 | accurate results, but is also very slow when the X connection has | ||
| 31597 | moderate to high latency. Setting this variable to a non-nil value | ||
| 31598 | makes Emacs query only for the position of the pointer, which is | ||
| 31599 | usually faster. Doing so improves the performance of dragging to | ||
| 31600 | select text over slow X connections. | ||
| 31601 | |||
| 31602 | If 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 | ||
| 1606 | extern void x_free_gcs (struct frame *); | 1608 | extern void x_free_gcs (struct frame *); |
| 1607 | extern void x_relative_mouse_position (struct frame *, int *, int *); | 1609 | extern void x_relative_mouse_position (struct frame *, int *, int *); |
| 1608 | extern void x_real_pos_and_offsets (struct frame *f, | 1610 | extern 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, | 1613 | extern 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); | ||
| 1618 | extern void x_default_font_parameter (struct frame* f, Lisp_Object parms); | ||
| 1619 | 1614 | ||
| 1620 | /* From xrdb.c. */ | 1615 | /* From xrdb.c. */ |
| 1621 | 1616 | ||
| 1622 | XrmDatabase x_load_resources (Display *, const char *, const char *, | 1617 | extern XrmDatabase x_load_resources (Display *, const char *, const char *, |
| 1623 | const char *); | 1618 | const char *); |
| 1624 | extern const char *x_get_string_resource (void *, const char *, const char *); | 1619 | extern const char *x_get_string_resource (void *, const char *, const char *); |
| 1625 | 1620 | ||
| 1626 | /* Defined in xterm.c */ | 1621 | /* Defined in xterm.c */ |