aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVibhav Pant2022-12-20 21:56:02 +0530
committerVibhav Pant2022-12-20 21:56:02 +0530
commite7459fcbde4e468f9dfc74477072c7405b59e03e (patch)
tree524457d1b9f6aa7edb393b540e4123d1fc60942b /src
parent89892db0af4f8a803eb7ff3f5f7880d3126702ff (diff)
parent9fafeb2a66fe1cba8f3ad7662196e36ca0b1eca7 (diff)
downloademacs-e7459fcbde4e468f9dfc74477072c7405b59e03e.tar.gz
emacs-e7459fcbde4e468f9dfc74477072c7405b59e03e.zip
Merge branch 'master' into scratch/comp-static-data
Diffstat (limited to 'src')
-rw-r--r--src/.lldbinit2
-rw-r--r--src/ChangeLog.112
-rw-r--r--src/ChangeLog.122
-rw-r--r--src/ChangeLog.132
-rw-r--r--src/ChangeLog.32
-rw-r--r--src/alloc.c289
-rw-r--r--src/buffer.c69
-rw-r--r--src/buffer.h14
-rw-r--r--src/data.c1
-rw-r--r--src/dispextern.h10
-rw-r--r--src/editfns.c397
-rw-r--r--src/emacs-module.h.in15
-rw-r--r--src/emacs.c7
-rw-r--r--src/fileio.c42
-rw-r--r--src/fns.c15
-rw-r--r--src/frame.c62
-rw-r--r--src/frame.h1
-rw-r--r--src/gnutls.c2
-rw-r--r--src/gtkutil.c6
-rw-r--r--src/image.c17
-rw-r--r--src/itree.c4
-rw-r--r--src/itree.h11
-rw-r--r--src/keyboard.c22
-rw-r--r--src/lisp.h23
-rw-r--r--src/lread.c27
-rw-r--r--src/module-env-29.h3
-rw-r--r--src/module-env-30.h3
-rw-r--r--src/pdumper.c7
-rw-r--r--src/sqlite.c15
-rw-r--r--src/sysdep.c7
-rw-r--r--src/timefns.c6
-rw-r--r--src/treesit.c683
-rw-r--r--src/treesit.h13
-rw-r--r--src/window.c10
-rw-r--r--src/xdisp.c143
-rw-r--r--src/xfaces.c90
-rw-r--r--src/xfns.c65
-rw-r--r--src/xftfont.c6
-rw-r--r--src/xselect.c940
-rw-r--r--src/xterm.c660
-rw-r--r--src/xterm.h63
41 files changed, 2820 insertions, 938 deletions
diff --git a/src/.lldbinit b/src/.lldbinit
index 358cea5f8b6..5fdac34b786 100644
--- a/src/.lldbinit
+++ b/src/.lldbinit
@@ -16,7 +16,7 @@
16# You should have received a copy of the GNU General Public License 16# You should have received a copy of the GNU General Public License
17# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 17# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
18# 18#
19# Use 'lldb --local-init' or add to your ~/.lldbinit the line 19# Use 'lldb --local-lldbinit' or add to your ~/.lldbinit the line
20# 20#
21# settings set target.load-cwd-lldbinit true 21# settings set target.load-cwd-lldbinit true
22# 22#
diff --git a/src/ChangeLog.11 b/src/ChangeLog.11
index a00ca453ca4..77180262aca 100644
--- a/src/ChangeLog.11
+++ b/src/ChangeLog.11
@@ -14235,7 +14235,7 @@
14235 ns_alternate_modifier. (Bug#1217) 14235 ns_alternate_modifier. (Bug#1217)
14236 14236
14237 * nsmenu.m (EmacsMenu-parseKeyEquiv:, addItemWithWidgetValue:): 14237 * nsmenu.m (EmacsMenu-parseKeyEquiv:, addItemWithWidgetValue:):
14238 Display all shortcuts, including those w/o super modifier. 14238 Display all shortcuts, including those without super modifier.
14239 14239
14240 * nsfns.m (ns-read-file-name): Fix typo in assignment statement. 14240 * nsfns.m (ns-read-file-name): Fix typo in assignment statement.
14241 14241
diff --git a/src/ChangeLog.12 b/src/ChangeLog.12
index 7f77c0ca077..f455c4de382 100644
--- a/src/ChangeLog.12
+++ b/src/ChangeLog.12
@@ -10836,7 +10836,7 @@
10836 * gtkutil.c (xg_maybe_add_timer): Port to higher-res time stamps. 10836 * gtkutil.c (xg_maybe_add_timer): Port to higher-res time stamps.
10837 10837
10838 * image.c (prepare_image_for_display, clear_image_cache) 10838 * image.c (prepare_image_for_display, clear_image_cache)
10839 (lookup_image): Port to higer-resolution time stamps. 10839 (lookup_image): Port to higher-resolution time stamps.
10840 10840
10841 * keyboard.c (start_polling, bind_polling_period): 10841 * keyboard.c (start_polling, bind_polling_period):
10842 Check for time stamp overflow. 10842 Check for time stamp overflow.
diff --git a/src/ChangeLog.13 b/src/ChangeLog.13
index 91f8005ac51..0c4e2909ced 100644
--- a/src/ChangeLog.13
+++ b/src/ChangeLog.13
@@ -10579,7 +10579,7 @@
10579 (../src/$(OLDXMENU), $(OLDXMENU)): Remove. 10579 (../src/$(OLDXMENU), $(OLDXMENU)): Remove.
10580 (temacs$(EXEEXT)): Depend on $(LIBXMENU), not stamp-oldxmenu. 10580 (temacs$(EXEEXT)): Depend on $(LIBXMENU), not stamp-oldxmenu.
10581 ($(lwlibdir)/liblw.a, $(oldXMenudir)/libXMenu11.a, FORCE): New targets. 10581 ($(lwlibdir)/liblw.a, $(oldXMenudir)/libXMenu11.a, FORCE): New targets.
10582 (boostrap-clean): No need to remove stamp-oldxmenu. 10582 (bootstrap-clean): No need to remove stamp-oldxmenu.
10583 10583
10584 Fix recently introduced bool vector overrun. 10584 Fix recently introduced bool vector overrun.
10585 This was due to an optimization that went awry. 10585 This was due to an optimization that went awry.
diff --git a/src/ChangeLog.3 b/src/ChangeLog.3
index 4b3675eaa8f..d32e894fa53 100644
--- a/src/ChangeLog.3
+++ b/src/ChangeLog.3
@@ -14422,7 +14422,7 @@
14422 * s-umips.h: Now include either s-usg5-2-2.h or s-bsd4-3.h 14422 * s-umips.h: Now include either s-usg5-2-2.h or s-bsd4-3.h
14423 and then override as needed. 14423 and then override as needed.
14424 * m-mips.h: System dependence deleted. 14424 * m-mips.h: System dependence deleted.
14425 LD_SWITCH_MACHINE remains w/ options needed on all systems. 14425 LD_SWITCH_MACHINE remains with options needed on all systems.
14426 * m-pmax.h: A little of that (LIBS_DEBUG) moved here. 14426 * m-pmax.h: A little of that (LIBS_DEBUG) moved here.
14427 No need to undef LIBS_MACHINE. 14427 No need to undef LIBS_MACHINE.
14428 14428
diff --git a/src/alloc.c b/src/alloc.c
index 0a8c1826614..0a4323d1ceb 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -82,6 +82,37 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
82#include <valgrind/memcheck.h> 82#include <valgrind/memcheck.h>
83#endif 83#endif
84 84
85/* AddressSanitizer exposes additional functions for manually marking
86 memory as poisoned/unpoisoned. When ASan is enabled and the needed
87 header is available, memory is poisoned when:
88
89 * An ablock is freed (lisp_align_free), or ablocks are initially
90 allocated (lisp_align_malloc).
91 * An interval_block is initially allocated (make_interval).
92 * A dead INTERVAL is put on the interval free list
93 (sweep_intervals).
94 * A sdata is marked as dead (sweep_strings, pin_string).
95 * An sblock is initially allocated (allocate_string_data).
96 * A string_block is initially allocated (allocate_string).
97 * A dead string is put on string_free_list (sweep_strings).
98 * A float_block is initially allocated (make_float).
99 * A dead float is put on float_free_list.
100 * A cons_block is initially allocated (Fcons).
101 * A dead cons is put on cons_free_list (sweep_cons).
102 * A dead vector is put on vector_free_list (setup_on_free_list),
103 or a new vector block is allocated (allocate_vector_from_block).
104 Accordingly, objects reused from the free list are unpoisoned.
105
106 This feature can be disabled wtih the run-time flag
107 `allow_user_poisoning' set to zero. */
108#if ADDRESS_SANITIZER && defined HAVE_SANITIZER_ASAN_INTERFACE_H \
109 && !defined GC_ASAN_POISON_OBJECTS
110# define GC_ASAN_POISON_OBJECTS 1
111# include <sanitizer/asan_interface.h>
112#else
113# define GC_ASAN_POISON_OBJECTS 0
114#endif
115
85/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. 116/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
86 We turn that on by default when ENABLE_CHECKING is defined; 117 We turn that on by default when ENABLE_CHECKING is defined;
87 define GC_CHECK_MARKED_OBJECTS to zero to disable. */ 118 define GC_CHECK_MARKED_OBJECTS to zero to disable. */
@@ -1164,6 +1195,16 @@ struct ablocks
1164 (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1]) 1195 (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1])
1165#endif 1196#endif
1166 1197
1198#if GC_ASAN_POISON_OBJECTS
1199# define ASAN_POISON_ABLOCK(b) \
1200 __asan_poison_memory_region (&(b)->x, sizeof ((b)->x))
1201# define ASAN_UNPOISON_ABLOCK(b) \
1202 __asan_unpoison_memory_region (&(b)->x, sizeof ((b)->x))
1203#else
1204# define ASAN_POISON_ABLOCK(b) ((void) 0)
1205# define ASAN_UNPOISON_ABLOCK(b) ((void) 0)
1206#endif
1207
1167/* The list of free ablock. */ 1208/* The list of free ablock. */
1168static struct ablock *free_ablock; 1209static struct ablock *free_ablock;
1169 1210
@@ -1242,6 +1283,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
1242 { 1283 {
1243 abase->blocks[i].abase = abase; 1284 abase->blocks[i].abase = abase;
1244 abase->blocks[i].x.next_free = free_ablock; 1285 abase->blocks[i].x.next_free = free_ablock;
1286 ASAN_POISON_ABLOCK (&abase->blocks[i]);
1245 free_ablock = &abase->blocks[i]; 1287 free_ablock = &abase->blocks[i];
1246 } 1288 }
1247 intptr_t ialigned = aligned; 1289 intptr_t ialigned = aligned;
@@ -1254,6 +1296,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
1254 eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned); 1296 eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned);
1255 } 1297 }
1256 1298
1299 ASAN_UNPOISON_ABLOCK (free_ablock);
1257 abase = ABLOCK_ABASE (free_ablock); 1300 abase = ABLOCK_ABASE (free_ablock);
1258 ABLOCKS_BUSY (abase) 1301 ABLOCKS_BUSY (abase)
1259 = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase)); 1302 = (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
@@ -1285,6 +1328,7 @@ lisp_align_free (void *block)
1285#endif 1328#endif
1286 /* Put on free list. */ 1329 /* Put on free list. */
1287 ablock->x.next_free = free_ablock; 1330 ablock->x.next_free = free_ablock;
1331 ASAN_POISON_ABLOCK (ablock);
1288 free_ablock = ablock; 1332 free_ablock = ablock;
1289 /* Update busy count. */ 1333 /* Update busy count. */
1290 intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2; 1334 intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2;
@@ -1297,9 +1341,12 @@ lisp_align_free (void *block)
1297 bool aligned = busy; 1341 bool aligned = busy;
1298 struct ablock **tem = &free_ablock; 1342 struct ablock **tem = &free_ablock;
1299 struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1]; 1343 struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1];
1300
1301 while (*tem) 1344 while (*tem)
1302 { 1345 {
1346#if GC_ASAN_POISON_OBJECTS
1347 __asan_unpoison_memory_region (&(*tem)->x,
1348 sizeof ((*tem)->x));
1349#endif
1303 if (*tem >= (struct ablock *) abase && *tem < atop) 1350 if (*tem >= (struct ablock *) abase && *tem < atop)
1304 { 1351 {
1305 i++; 1352 i++;
@@ -1428,6 +1475,24 @@ static int interval_block_index = INTERVAL_BLOCK_SIZE;
1428 1475
1429static INTERVAL interval_free_list; 1476static INTERVAL interval_free_list;
1430 1477
1478#if GC_ASAN_POISON_OBJECTS
1479# define ASAN_POISON_INTERVAL_BLOCK(b) \
1480 __asan_poison_memory_region ((b)->intervals, \
1481 sizeof ((b)->intervals))
1482# define ASAN_UNPOISON_INTERVAL_BLOCK(b) \
1483 __asan_unpoison_memory_region ((b)->intervals, \
1484 sizeof ((b)->intervals))
1485# define ASAN_POISON_INTERVAL(i) \
1486 __asan_poison_memory_region ((i), sizeof (*(i)))
1487# define ASAN_UNPOISON_INTERVAL(i) \
1488 __asan_unpoison_memory_region ((i), sizeof (*(i)))
1489#else
1490# define ASAN_POISON_INTERVAL_BLOCK(b) ((void) 0)
1491# define ASAN_UNPOISON_INTERVAL_BLOCK(b) ((void) 0)
1492# define ASAN_POISON_INTERVAL(i) ((void) 0)
1493# define ASAN_UNPOISON_INTERVAL(i) ((void) 0)
1494#endif
1495
1431/* Return a new interval. */ 1496/* Return a new interval. */
1432 1497
1433INTERVAL 1498INTERVAL
@@ -1440,6 +1505,7 @@ make_interval (void)
1440 if (interval_free_list) 1505 if (interval_free_list)
1441 { 1506 {
1442 val = interval_free_list; 1507 val = interval_free_list;
1508 ASAN_UNPOISON_INTERVAL (val);
1443 interval_free_list = INTERVAL_PARENT (interval_free_list); 1509 interval_free_list = INTERVAL_PARENT (interval_free_list);
1444 } 1510 }
1445 else 1511 else
@@ -1450,10 +1516,12 @@ make_interval (void)
1450 = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP); 1516 = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP);
1451 1517
1452 newi->next = interval_block; 1518 newi->next = interval_block;
1519 ASAN_POISON_INTERVAL_BLOCK (newi);
1453 interval_block = newi; 1520 interval_block = newi;
1454 interval_block_index = 0; 1521 interval_block_index = 0;
1455 } 1522 }
1456 val = &interval_block->intervals[interval_block_index++]; 1523 val = &interval_block->intervals[interval_block_index++];
1524 ASAN_UNPOISON_INTERVAL (val);
1457 } 1525 }
1458 1526
1459 MALLOC_UNBLOCK_INPUT; 1527 MALLOC_UNBLOCK_INPUT;
@@ -1694,6 +1762,41 @@ init_strings (void)
1694 staticpro (&empty_multibyte_string); 1762 staticpro (&empty_multibyte_string);
1695} 1763}
1696 1764
1765#if GC_ASAN_POISON_OBJECTS
1766/* Prepare s for denoting a free sdata struct, i.e, poison all bytes
1767 in the flexible array member, except the first SDATA_OFFSET bytes.
1768 This is only effective for strings of size n where n > sdata_size(n).
1769 */
1770# define ASAN_PREPARE_DEAD_SDATA(s, size) \
1771 do { \
1772 __asan_poison_memory_region ((s), sdata_size ((size))); \
1773 __asan_unpoison_memory_region (&(((s))->string), \
1774 sizeof (struct Lisp_String *)); \
1775 __asan_unpoison_memory_region (&SDATA_NBYTES ((s)), \
1776 sizeof (SDATA_NBYTES ((s)))); \
1777 } while (false)
1778/* Prepare s for storing string data for NBYTES bytes. */
1779# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) \
1780 __asan_unpoison_memory_region ((s), sdata_size ((nbytes)))
1781# define ASAN_POISON_SBLOCK_DATA(b, size) \
1782 __asan_poison_memory_region ((b)->data, (size))
1783# define ASAN_POISON_STRING_BLOCK(b) \
1784 __asan_poison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1785# define ASAN_UNPOISON_STRING_BLOCK(b) \
1786 __asan_unpoison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
1787# define ASAN_POISON_STRING(s) \
1788 __asan_poison_memory_region ((s), sizeof (*(s)))
1789# define ASAN_UNPOISON_STRING(s) \
1790 __asan_unpoison_memory_region ((s), sizeof (*(s)))
1791#else
1792# define ASAN_PREPARE_DEAD_SDATA(s, size) ((void) 0)
1793# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) ((void) 0)
1794# define ASAN_POISON_SBLOCK_DATA(b, size) ((void) 0)
1795# define ASAN_POISON_STRING_BLOCK(b) ((void) 0)
1796# define ASAN_UNPOISON_STRING_BLOCK(b) ((void) 0)
1797# define ASAN_POISON_STRING(s) ((void) 0)
1798# define ASAN_UNPOISON_STRING(s) ((void) 0)
1799#endif
1697 1800
1698#ifdef GC_CHECK_STRING_BYTES 1801#ifdef GC_CHECK_STRING_BYTES
1699 1802
@@ -1812,12 +1915,14 @@ allocate_string (void)
1812 NEXT_FREE_LISP_STRING (s) = string_free_list; 1915 NEXT_FREE_LISP_STRING (s) = string_free_list;
1813 string_free_list = s; 1916 string_free_list = s;
1814 } 1917 }
1918 ASAN_POISON_STRING_BLOCK (b);
1815 } 1919 }
1816 1920
1817 check_string_free_list (); 1921 check_string_free_list ();
1818 1922
1819 /* Pop a Lisp_String off the free-list. */ 1923 /* Pop a Lisp_String off the free-list. */
1820 s = string_free_list; 1924 s = string_free_list;
1925 ASAN_UNPOISON_STRING (s);
1821 string_free_list = NEXT_FREE_LISP_STRING (s); 1926 string_free_list = NEXT_FREE_LISP_STRING (s);
1822 1927
1823 MALLOC_UNBLOCK_INPUT; 1928 MALLOC_UNBLOCK_INPUT;
@@ -1877,6 +1982,7 @@ allocate_string_data (struct Lisp_String *s,
1877#endif 1982#endif
1878 1983
1879 b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP); 1984 b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP);
1985 ASAN_POISON_SBLOCK_DATA (b, size);
1880 1986
1881#ifdef DOUG_LEA_MALLOC 1987#ifdef DOUG_LEA_MALLOC
1882 if (!mmap_lisp_allowed_p ()) 1988 if (!mmap_lisp_allowed_p ())
@@ -1898,6 +2004,8 @@ allocate_string_data (struct Lisp_String *s,
1898 { 2004 {
1899 /* Not enough room in the current sblock. */ 2005 /* Not enough room in the current sblock. */
1900 b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP); 2006 b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP);
2007 ASAN_POISON_SBLOCK_DATA (b, SBLOCK_SIZE);
2008
1901 data = b->data; 2009 data = b->data;
1902 b->next = NULL; 2010 b->next = NULL;
1903 b->next_free = data; 2011 b->next_free = data;
@@ -1910,10 +2018,19 @@ allocate_string_data (struct Lisp_String *s,
1910 } 2018 }
1911 2019
1912 data = b->next_free; 2020 data = b->next_free;
2021
1913 if (clearit) 2022 if (clearit)
1914 memset (SDATA_DATA (data), 0, nbytes); 2023 {
2024#if GC_ASAN_POISON_OBJECTS
2025 /* We are accessing SDATA_DATA (data) before it gets
2026 * normally unpoisoned, so do it manually. */
2027 __asan_unpoison_memory_region (SDATA_DATA (data), nbytes);
2028#endif
2029 memset (SDATA_DATA (data), 0, nbytes);
2030 }
1915 } 2031 }
1916 2032
2033 ASAN_PREPARE_LIVE_SDATA (data, nbytes);
1917 data->string = s; 2034 data->string = s;
1918 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA); 2035 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
1919 eassert ((uintptr_t) b->next_free % alignof (sdata) == 0); 2036 eassert ((uintptr_t) b->next_free % alignof (sdata) == 0);
@@ -2005,12 +2122,16 @@ sweep_strings (void)
2005 int i, nfree = 0; 2122 int i, nfree = 0;
2006 struct Lisp_String *free_list_before = string_free_list; 2123 struct Lisp_String *free_list_before = string_free_list;
2007 2124
2125 ASAN_UNPOISON_STRING_BLOCK (b);
2126
2008 next = b->next; 2127 next = b->next;
2009 2128
2010 for (i = 0; i < STRING_BLOCK_SIZE; ++i) 2129 for (i = 0; i < STRING_BLOCK_SIZE; ++i)
2011 { 2130 {
2012 struct Lisp_String *s = b->strings + i; 2131 struct Lisp_String *s = b->strings + i;
2013 2132
2133 ASAN_UNPOISON_STRING (s);
2134
2014 if (s->u.s.data) 2135 if (s->u.s.data)
2015 { 2136 {
2016 /* String was not on free-list before. */ 2137 /* String was not on free-list before. */
@@ -2047,6 +2168,8 @@ sweep_strings (void)
2047 2168
2048 /* Put the string on the free-list. */ 2169 /* Put the string on the free-list. */
2049 NEXT_FREE_LISP_STRING (s) = string_free_list; 2170 NEXT_FREE_LISP_STRING (s) = string_free_list;
2171 ASAN_POISON_STRING (s);
2172 ASAN_PREPARE_DEAD_SDATA (data, SDATA_NBYTES (data));
2050 string_free_list = s; 2173 string_free_list = s;
2051 ++nfree; 2174 ++nfree;
2052 } 2175 }
@@ -2055,6 +2178,8 @@ sweep_strings (void)
2055 { 2178 {
2056 /* S was on the free-list before. Put it there again. */ 2179 /* S was on the free-list before. Put it there again. */
2057 NEXT_FREE_LISP_STRING (s) = string_free_list; 2180 NEXT_FREE_LISP_STRING (s) = string_free_list;
2181 ASAN_POISON_STRING (s);
2182
2058 string_free_list = s; 2183 string_free_list = s;
2059 ++nfree; 2184 ++nfree;
2060 } 2185 }
@@ -2181,6 +2306,7 @@ compact_small_strings (void)
2181 if (from != to) 2306 if (from != to)
2182 { 2307 {
2183 eassert (tb != b || to < from); 2308 eassert (tb != b || to < from);
2309 ASAN_PREPARE_LIVE_SDATA (to, nbytes);
2184 memmove (to, from, size + GC_STRING_EXTRA); 2310 memmove (to, from, size + GC_STRING_EXTRA);
2185 to->string->u.s.data = SDATA_DATA (to); 2311 to->string->u.s.data = SDATA_DATA (to);
2186 } 2312 }
@@ -2537,6 +2663,7 @@ pin_string (Lisp_Object string)
2537 memcpy (s->u.s.data, data, size); 2663 memcpy (s->u.s.data, data, size);
2538 old_sdata->string = NULL; 2664 old_sdata->string = NULL;
2539 SDATA_NBYTES (old_sdata) = size; 2665 SDATA_NBYTES (old_sdata) = size;
2666 ASAN_PREPARE_DEAD_SDATA (old_sdata, size);
2540 } 2667 }
2541 if (s->u.s.size_byte != -3) 2668 if (s->u.s.size_byte != -3)
2542 s->u.s.size_byte = -3; 2669 s->u.s.size_byte = -3;
@@ -2601,6 +2728,24 @@ struct float_block
2601#define XFLOAT_UNMARK(fptr) \ 2728#define XFLOAT_UNMARK(fptr) \
2602 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr))) 2729 UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
2603 2730
2731#if GC_ASAN_POISON_OBJECTS
2732# define ASAN_POISON_FLOAT_BLOCK(fblk) \
2733 __asan_poison_memory_region ((fblk)->floats, \
2734 sizeof ((fblk)->floats))
2735# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) \
2736 __asan_unpoison_memory_region ((fblk)->floats, \
2737 sizeof ((fblk)->floats))
2738# define ASAN_POISON_FLOAT(p) \
2739 __asan_poison_memory_region ((p), sizeof (struct Lisp_Float))
2740# define ASAN_UNPOISON_FLOAT(p) \
2741 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Float))
2742#else
2743# define ASAN_POISON_FLOAT_BLOCK(fblk) ((void) 0)
2744# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) ((void) 0)
2745# define ASAN_POISON_FLOAT(p) ((void) 0)
2746# define ASAN_UNPOISON_FLOAT(p) ((void) 0)
2747#endif
2748
2604/* Current float_block. */ 2749/* Current float_block. */
2605 2750
2606static struct float_block *float_block; 2751static struct float_block *float_block;
@@ -2625,6 +2770,7 @@ make_float (double float_value)
2625 if (float_free_list) 2770 if (float_free_list)
2626 { 2771 {
2627 XSETFLOAT (val, float_free_list); 2772 XSETFLOAT (val, float_free_list);
2773 ASAN_UNPOISON_FLOAT (float_free_list);
2628 float_free_list = float_free_list->u.chain; 2774 float_free_list = float_free_list->u.chain;
2629 } 2775 }
2630 else 2776 else
@@ -2635,9 +2781,11 @@ make_float (double float_value)
2635 = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT); 2781 = lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT);
2636 new->next = float_block; 2782 new->next = float_block;
2637 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2783 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2784 ASAN_POISON_FLOAT_BLOCK (new);
2638 float_block = new; 2785 float_block = new;
2639 float_block_index = 0; 2786 float_block_index = 0;
2640 } 2787 }
2788 ASAN_UNPOISON_FLOAT (&float_block->floats[float_block_index]);
2641 XSETFLOAT (val, &float_block->floats[float_block_index]); 2789 XSETFLOAT (val, &float_block->floats[float_block_index]);
2642 float_block_index++; 2790 float_block_index++;
2643 } 2791 }
@@ -2715,6 +2863,19 @@ static int cons_block_index = CONS_BLOCK_SIZE;
2715 2863
2716static struct Lisp_Cons *cons_free_list; 2864static struct Lisp_Cons *cons_free_list;
2717 2865
2866#if GC_ASAN_POISON_OBJECTS
2867# define ASAN_POISON_CONS_BLOCK(b) \
2868 __asan_poison_memory_region ((b)->conses, sizeof ((b)->conses))
2869# define ASAN_POISON_CONS(p) \
2870 __asan_poison_memory_region ((p), sizeof (struct Lisp_Cons))
2871# define ASAN_UNPOISON_CONS(p) \
2872 __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Cons))
2873#else
2874# define ASAN_POISON_CONS_BLOCK(b) ((void) 0)
2875# define ASAN_POISON_CONS(p) ((void) 0)
2876# define ASAN_UNPOISON_CONS(p) ((void) 0)
2877#endif
2878
2718/* Explicitly free a cons cell by putting it on the free-list. */ 2879/* Explicitly free a cons cell by putting it on the free-list. */
2719 2880
2720void 2881void
@@ -2725,6 +2886,7 @@ free_cons (struct Lisp_Cons *ptr)
2725 cons_free_list = ptr; 2886 cons_free_list = ptr;
2726 ptrdiff_t nbytes = sizeof *ptr; 2887 ptrdiff_t nbytes = sizeof *ptr;
2727 tally_consing (-nbytes); 2888 tally_consing (-nbytes);
2889 ASAN_POISON_CONS (ptr);
2728} 2890}
2729 2891
2730DEFUN ("cons", Fcons, Scons, 2, 2, 0, 2892DEFUN ("cons", Fcons, Scons, 2, 2, 0,
@@ -2737,6 +2899,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2737 2899
2738 if (cons_free_list) 2900 if (cons_free_list)
2739 { 2901 {
2902 ASAN_UNPOISON_CONS (cons_free_list);
2740 XSETCONS (val, cons_free_list); 2903 XSETCONS (val, cons_free_list);
2741 cons_free_list = cons_free_list->u.s.u.chain; 2904 cons_free_list = cons_free_list->u.s.u.chain;
2742 } 2905 }
@@ -2747,10 +2910,12 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
2747 struct cons_block *new 2910 struct cons_block *new
2748 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS); 2911 = lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
2749 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); 2912 memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
2913 ASAN_POISON_CONS_BLOCK (new);
2750 new->next = cons_block; 2914 new->next = cons_block;
2751 cons_block = new; 2915 cons_block = new;
2752 cons_block_index = 0; 2916 cons_block_index = 0;
2753 } 2917 }
2918 ASAN_UNPOISON_CONS (&cons_block->conses[cons_block_index]);
2754 XSETCONS (val, &cons_block->conses[cons_block_index]); 2919 XSETCONS (val, &cons_block->conses[cons_block_index]);
2755 cons_block_index++; 2920 cons_block_index++;
2756 } 2921 }
@@ -3005,6 +3170,19 @@ static struct large_vector *large_vectors;
3005 3170
3006Lisp_Object zero_vector; 3171Lisp_Object zero_vector;
3007 3172
3173#if GC_ASAN_POISON_OBJECTS
3174# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) \
3175 __asan_poison_memory_region ((v)->contents, (bytes))
3176# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) \
3177 __asan_unpoison_memory_region ((v)->contents, (bytes))
3178# define ASAN_UNPOISON_VECTOR_BLOCK(b) \
3179 __asan_unpoison_memory_region ((b)->data, sizeof ((b)->data))
3180#else
3181# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3182# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
3183# define ASAN_UNPOISON_VECTOR_BLOCK(b) ((void) 0)
3184#endif
3185
3008/* Common shortcut to setup vector on a free list. */ 3186/* Common shortcut to setup vector on a free list. */
3009 3187
3010static void 3188static void
@@ -3017,6 +3195,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
3017 ptrdiff_t vindex = VINDEX (nbytes); 3195 ptrdiff_t vindex = VINDEX (nbytes);
3018 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX); 3196 eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
3019 set_next_vector (v, vector_free_lists[vindex]); 3197 set_next_vector (v, vector_free_lists[vindex]);
3198 ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
3020 vector_free_lists[vindex] = v; 3199 vector_free_lists[vindex] = v;
3021} 3200}
3022 3201
@@ -3064,6 +3243,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3064 if (vector_free_lists[index]) 3243 if (vector_free_lists[index])
3065 { 3244 {
3066 vector = vector_free_lists[index]; 3245 vector = vector_free_lists[index];
3246 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3067 vector_free_lists[index] = next_vector (vector); 3247 vector_free_lists[index] = next_vector (vector);
3068 return vector; 3248 return vector;
3069 } 3249 }
@@ -3077,12 +3257,18 @@ allocate_vector_from_block (ptrdiff_t nbytes)
3077 { 3257 {
3078 /* This vector is larger than requested. */ 3258 /* This vector is larger than requested. */
3079 vector = vector_free_lists[index]; 3259 vector = vector_free_lists[index];
3260 ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
3080 vector_free_lists[index] = next_vector (vector); 3261 vector_free_lists[index] = next_vector (vector);
3081 3262
3082 /* Excess bytes are used for the smaller vector, 3263 /* Excess bytes are used for the smaller vector,
3083 which should be set on an appropriate free list. */ 3264 which should be set on an appropriate free list. */
3084 restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; 3265 restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
3085 eassert (restbytes % roundup_size == 0); 3266 eassert (restbytes % roundup_size == 0);
3267#if GC_ASAN_POISON_OBJECTS
3268 /* Ensure that accessing excess bytes does not trigger ASan. */
3269 __asan_unpoison_memory_region (ADVANCE (vector, nbytes),
3270 restbytes);
3271#endif
3086 setup_on_free_list (ADVANCE (vector, nbytes), restbytes); 3272 setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
3087 return vector; 3273 return vector;
3088 } 3274 }
@@ -3258,6 +3444,7 @@ sweep_vectors (void)
3258 for (vector = (struct Lisp_Vector *) block->data; 3444 for (vector = (struct Lisp_Vector *) block->data;
3259 VECTOR_IN_BLOCK (vector, block); vector = next) 3445 VECTOR_IN_BLOCK (vector, block); vector = next)
3260 { 3446 {
3447 ASAN_UNPOISON_VECTOR_BLOCK (block);
3261 if (XVECTOR_MARKED_P (vector)) 3448 if (XVECTOR_MARKED_P (vector))
3262 { 3449 {
3263 XUNMARK_VECTOR (vector); 3450 XUNMARK_VECTOR (vector);
@@ -3633,6 +3820,23 @@ struct symbol_block
3633 struct symbol_block *next; 3820 struct symbol_block *next;
3634}; 3821};
3635 3822
3823#if GC_ASAN_POISON_OBJECTS
3824# define ASAN_POISON_SYMBOL_BLOCK(s) \
3825 __asan_poison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3826# define ASAN_UNPOISON_SYMBOL_BLOCK(s) \
3827 __asan_unpoison_memory_region ((s)->symbols, sizeof ((s)->symbols))
3828# define ASAN_POISON_SYMBOL(sym) \
3829 __asan_poison_memory_region ((sym), sizeof (*(sym)))
3830# define ASAN_UNPOISON_SYMBOL(sym) \
3831 __asan_unpoison_memory_region ((sym), sizeof (*(sym)))
3832
3833#else
3834# define ASAN_POISON_SYMBOL_BLOCK(s) ((void) 0)
3835# define ASAN_UNPOISON_SYMBOL_BLOCK(s) ((void) 0)
3836# define ASAN_POISON_SYMBOL(sym) ((void) 0)
3837# define ASAN_UNPOISON_SYMBOL(sym) ((void) 0)
3838#endif
3839
3636/* Current symbol block and index of first unused Lisp_Symbol 3840/* Current symbol block and index of first unused Lisp_Symbol
3637 structure in it. */ 3841 structure in it. */
3638 3842
@@ -3686,6 +3890,7 @@ Its value is void, and its function definition and property list are nil. */)
3686 3890
3687 if (symbol_free_list) 3891 if (symbol_free_list)
3688 { 3892 {
3893 ASAN_UNPOISON_SYMBOL (symbol_free_list);
3689 XSETSYMBOL (val, symbol_free_list); 3894 XSETSYMBOL (val, symbol_free_list);
3690 symbol_free_list = symbol_free_list->u.s.next; 3895 symbol_free_list = symbol_free_list->u.s.next;
3691 } 3896 }
@@ -3695,10 +3900,13 @@ Its value is void, and its function definition and property list are nil. */)
3695 { 3900 {
3696 struct symbol_block *new 3901 struct symbol_block *new
3697 = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL); 3902 = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL);
3903 ASAN_POISON_SYMBOL_BLOCK (new);
3698 new->next = symbol_block; 3904 new->next = symbol_block;
3699 symbol_block = new; 3905 symbol_block = new;
3700 symbol_block_index = 0; 3906 symbol_block_index = 0;
3701 } 3907 }
3908
3909 ASAN_UNPOISON_SYMBOL (&symbol_block->symbols[symbol_block_index]);
3702 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); 3910 XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
3703 symbol_block_index++; 3911 symbol_block_index++;
3704 } 3912 }
@@ -4624,6 +4832,11 @@ static struct Lisp_String *
4624live_string_holding (struct mem_node *m, void *p) 4832live_string_holding (struct mem_node *m, void *p)
4625{ 4833{
4626 eassert (m->type == MEM_TYPE_STRING); 4834 eassert (m->type == MEM_TYPE_STRING);
4835#if GC_ASAN_POISON_OBJECTS
4836 if (__asan_address_is_poisoned (p))
4837 return NULL;
4838#endif
4839
4627 struct string_block *b = m->start; 4840 struct string_block *b = m->start;
4628 char *cp = p; 4841 char *cp = p;
4629 ptrdiff_t offset = cp - (char *) &b->strings[0]; 4842 ptrdiff_t offset = cp - (char *) &b->strings[0];
@@ -4640,6 +4853,10 @@ live_string_holding (struct mem_node *m, void *p)
4640 || off == offsetof (struct Lisp_String, u.s.data)) 4853 || off == offsetof (struct Lisp_String, u.s.data))
4641 { 4854 {
4642 struct Lisp_String *s = p = cp -= off; 4855 struct Lisp_String *s = p = cp -= off;
4856#if GC_ASAN_POISON_OBJECTS
4857 if (__asan_region_is_poisoned (s, sizeof (*s)))
4858 return NULL;
4859#endif
4643 if (s->u.s.data) 4860 if (s->u.s.data)
4644 return s; 4861 return s;
4645 } 4862 }
@@ -4661,6 +4878,11 @@ static struct Lisp_Cons *
4661live_cons_holding (struct mem_node *m, void *p) 4878live_cons_holding (struct mem_node *m, void *p)
4662{ 4879{
4663 eassert (m->type == MEM_TYPE_CONS); 4880 eassert (m->type == MEM_TYPE_CONS);
4881#if GC_ASAN_POISON_OBJECTS
4882 if (__asan_address_is_poisoned (p))
4883 return NULL;
4884#endif
4885
4664 struct cons_block *b = m->start; 4886 struct cons_block *b = m->start;
4665 char *cp = p; 4887 char *cp = p;
4666 ptrdiff_t offset = cp - (char *) &b->conses[0]; 4888 ptrdiff_t offset = cp - (char *) &b->conses[0];
@@ -4678,6 +4900,10 @@ live_cons_holding (struct mem_node *m, void *p)
4678 || off == offsetof (struct Lisp_Cons, u.s.u.cdr)) 4900 || off == offsetof (struct Lisp_Cons, u.s.u.cdr))
4679 { 4901 {
4680 struct Lisp_Cons *s = p = cp -= off; 4902 struct Lisp_Cons *s = p = cp -= off;
4903#if GC_ASAN_POISON_OBJECTS
4904 if (__asan_region_is_poisoned (s, sizeof (*s)))
4905 return NULL;
4906#endif
4681 if (!deadp (s->u.s.car)) 4907 if (!deadp (s->u.s.car))
4682 return s; 4908 return s;
4683 } 4909 }
@@ -4700,6 +4926,10 @@ static struct Lisp_Symbol *
4700live_symbol_holding (struct mem_node *m, void *p) 4926live_symbol_holding (struct mem_node *m, void *p)
4701{ 4927{
4702 eassert (m->type == MEM_TYPE_SYMBOL); 4928 eassert (m->type == MEM_TYPE_SYMBOL);
4929#if GC_ASAN_POISON_OBJECTS
4930 if (__asan_address_is_poisoned (p))
4931 return NULL;
4932#endif
4703 struct symbol_block *b = m->start; 4933 struct symbol_block *b = m->start;
4704 char *cp = p; 4934 char *cp = p;
4705 ptrdiff_t offset = cp - (char *) &b->symbols[0]; 4935 ptrdiff_t offset = cp - (char *) &b->symbols[0];
@@ -4725,6 +4955,10 @@ live_symbol_holding (struct mem_node *m, void *p)
4725 || off == offsetof (struct Lisp_Symbol, u.s.next)) 4955 || off == offsetof (struct Lisp_Symbol, u.s.next))
4726 { 4956 {
4727 struct Lisp_Symbol *s = p = cp -= off; 4957 struct Lisp_Symbol *s = p = cp -= off;
4958#if GC_ASAN_POISON_OBJECTS
4959 if (__asan_region_is_poisoned (s, sizeof (*s)))
4960 return NULL;
4961#endif
4728 if (!deadp (s->u.s.function)) 4962 if (!deadp (s->u.s.function))
4729 return s; 4963 return s;
4730 } 4964 }
@@ -4747,6 +4981,11 @@ static struct Lisp_Float *
4747live_float_holding (struct mem_node *m, void *p) 4981live_float_holding (struct mem_node *m, void *p)
4748{ 4982{
4749 eassert (m->type == MEM_TYPE_FLOAT); 4983 eassert (m->type == MEM_TYPE_FLOAT);
4984#if GC_ASAN_POISON_OBJECTS
4985 if (__asan_address_is_poisoned (p))
4986 return NULL;
4987#endif
4988
4750 struct float_block *b = m->start; 4989 struct float_block *b = m->start;
4751 char *cp = p; 4990 char *cp = p;
4752 ptrdiff_t offset = cp - (char *) &b->floats[0]; 4991 ptrdiff_t offset = cp - (char *) &b->floats[0];
@@ -4761,8 +5000,12 @@ live_float_holding (struct mem_node *m, void *p)
4761 && (b != float_block 5000 && (b != float_block
4762 || offset / sizeof b->floats[0] < float_block_index)) 5001 || offset / sizeof b->floats[0] < float_block_index))
4763 { 5002 {
4764 p = cp - off; 5003 struct Lisp_Float *f = (struct Lisp_Float *) (cp - off);
4765 return p; 5004#if GC_ASAN_POISON_OBJECTS
5005 if (__asan_region_is_poisoned (f, sizeof (*f)))
5006 return NULL;
5007#endif
5008 return f;
4766 } 5009 }
4767 } 5010 }
4768 return NULL; 5011 return NULL;
@@ -5338,7 +5581,8 @@ valid_lisp_object_p (Lisp_Object obj)
5338 if (valid <= 0) 5581 if (valid <= 0)
5339 return valid; 5582 return valid;
5340 5583
5341 if (SUBRP (obj)) 5584 /* Strings and conses produced by AUTO_STRING etc. all get here. */
5585 if (SUBRP (obj) || STRINGP (obj) || CONSP (obj))
5342 return 1; 5586 return 1;
5343 5587
5344#ifdef HAVE_STATIC_LISP_GLOBALS 5588#ifdef HAVE_STATIC_LISP_GLOBALS
@@ -6287,6 +6531,7 @@ garbage_collect (void)
6287 6531
6288#ifdef HAVE_X_WINDOWS 6532#ifdef HAVE_X_WINDOWS
6289 mark_xterm (); 6533 mark_xterm ();
6534 mark_xselect ();
6290#endif 6535#endif
6291 6536
6292#ifdef HAVE_NS 6537#ifdef HAVE_NS
@@ -6647,7 +6892,7 @@ mark_buffer (struct buffer *buffer)
6647 if (!BUFFER_LIVE_P (buffer)) 6892 if (!BUFFER_LIVE_P (buffer))
6648 mark_object (BVAR (buffer, undo_list)); 6893 mark_object (BVAR (buffer, undo_list));
6649 6894
6650 if (buffer->overlays) 6895 if (!itree_empty_p (buffer->overlays))
6651 mark_overlays (buffer->overlays->root); 6896 mark_overlays (buffer->overlays->root);
6652 6897
6653 /* If this is an indirect buffer, mark its base buffer. */ 6898 /* If this is an indirect buffer, mark its base buffer. */
@@ -7292,11 +7537,13 @@ sweep_conses (void)
7292 struct Lisp_Cons *acons = &cblk->conses[pos]; 7537 struct Lisp_Cons *acons = &cblk->conses[pos];
7293 if (!XCONS_MARKED_P (acons)) 7538 if (!XCONS_MARKED_P (acons))
7294 { 7539 {
7540 ASAN_UNPOISON_CONS (&cblk->conses[pos]);
7295 this_free++; 7541 this_free++;
7296 cblk->conses[pos].u.s.u.chain = cons_free_list; 7542 cblk->conses[pos].u.s.u.chain = cons_free_list;
7297 cons_free_list = &cblk->conses[pos]; 7543 cons_free_list = &cblk->conses[pos];
7298 cons_free_list->u.s.car = dead_object (); 7544 cons_free_list->u.s.car = dead_object ();
7299 } 7545 ASAN_POISON_CONS (&cblk->conses[pos]);
7546 }
7300 else 7547 else
7301 { 7548 {
7302 num_used++; 7549 num_used++;
@@ -7314,6 +7561,7 @@ sweep_conses (void)
7314 { 7561 {
7315 *cprev = cblk->next; 7562 *cprev = cblk->next;
7316 /* Unhook from the free list. */ 7563 /* Unhook from the free list. */
7564 ASAN_UNPOISON_CONS (&cblk->conses[0]);
7317 cons_free_list = cblk->conses[0].u.s.u.chain; 7565 cons_free_list = cblk->conses[0].u.s.u.chain;
7318 lisp_align_free (cblk); 7566 lisp_align_free (cblk);
7319 } 7567 }
@@ -7340,6 +7588,7 @@ sweep_floats (void)
7340 for (struct float_block *fblk; (fblk = *fprev); ) 7588 for (struct float_block *fblk; (fblk = *fprev); )
7341 { 7589 {
7342 int this_free = 0; 7590 int this_free = 0;
7591 ASAN_UNPOISON_FLOAT_BLOCK (fblk);
7343 for (int i = 0; i < lim; i++) 7592 for (int i = 0; i < lim; i++)
7344 { 7593 {
7345 struct Lisp_Float *afloat = &fblk->floats[i]; 7594 struct Lisp_Float *afloat = &fblk->floats[i];
@@ -7347,6 +7596,7 @@ sweep_floats (void)
7347 { 7596 {
7348 this_free++; 7597 this_free++;
7349 fblk->floats[i].u.chain = float_free_list; 7598 fblk->floats[i].u.chain = float_free_list;
7599 ASAN_POISON_FLOAT (&fblk->floats[i]);
7350 float_free_list = &fblk->floats[i]; 7600 float_free_list = &fblk->floats[i];
7351 } 7601 }
7352 else 7602 else
@@ -7363,7 +7613,8 @@ sweep_floats (void)
7363 { 7613 {
7364 *fprev = fblk->next; 7614 *fprev = fblk->next;
7365 /* Unhook from the free list. */ 7615 /* Unhook from the free list. */
7366 float_free_list = fblk->floats[0].u.chain; 7616 ASAN_UNPOISON_FLOAT (&fblk->floats[0]);
7617 float_free_list = fblk->floats[0].u.chain;
7367 lisp_align_free (fblk); 7618 lisp_align_free (fblk);
7368 } 7619 }
7369 else 7620 else
@@ -7389,13 +7640,14 @@ sweep_intervals (void)
7389 for (struct interval_block *iblk; (iblk = *iprev); ) 7640 for (struct interval_block *iblk; (iblk = *iprev); )
7390 { 7641 {
7391 int this_free = 0; 7642 int this_free = 0;
7392 7643 ASAN_UNPOISON_INTERVAL_BLOCK (iblk);
7393 for (int i = 0; i < lim; i++) 7644 for (int i = 0; i < lim; i++)
7394 { 7645 {
7395 if (!iblk->intervals[i].gcmarkbit) 7646 if (!iblk->intervals[i].gcmarkbit)
7396 { 7647 {
7397 set_interval_parent (&iblk->intervals[i], interval_free_list); 7648 set_interval_parent (&iblk->intervals[i], interval_free_list);
7398 interval_free_list = &iblk->intervals[i]; 7649 interval_free_list = &iblk->intervals[i];
7650 ASAN_POISON_INTERVAL (&iblk->intervals[i]);
7399 this_free++; 7651 this_free++;
7400 } 7652 }
7401 else 7653 else
@@ -7412,6 +7664,7 @@ sweep_intervals (void)
7412 { 7664 {
7413 *iprev = iblk->next; 7665 *iprev = iblk->next;
7414 /* Unhook from the free list. */ 7666 /* Unhook from the free list. */
7667 ASAN_UNPOISON_INTERVAL (&iblk->intervals[0]);
7415 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]); 7668 interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
7416 lisp_free (iblk); 7669 lisp_free (iblk);
7417 } 7670 }
@@ -7441,6 +7694,8 @@ sweep_symbols (void)
7441 7694
7442 for (sblk = symbol_block; sblk; sblk = *sprev) 7695 for (sblk = symbol_block; sblk; sblk = *sprev)
7443 { 7696 {
7697 ASAN_UNPOISON_SYMBOL_BLOCK (sblk);
7698
7444 int this_free = 0; 7699 int this_free = 0;
7445 struct Lisp_Symbol *sym = sblk->symbols; 7700 struct Lisp_Symbol *sym = sblk->symbols;
7446 struct Lisp_Symbol *end = sym + lim; 7701 struct Lisp_Symbol *end = sym + lim;
@@ -7462,7 +7717,8 @@ sweep_symbols (void)
7462 sym->u.s.next = symbol_free_list; 7717 sym->u.s.next = symbol_free_list;
7463 symbol_free_list = sym; 7718 symbol_free_list = sym;
7464 symbol_free_list->u.s.function = dead_object (); 7719 symbol_free_list->u.s.function = dead_object ();
7465 ++this_free; 7720 ASAN_POISON_SYMBOL (sym);
7721 ++this_free;
7466 } 7722 }
7467 else 7723 else
7468 { 7724 {
@@ -7481,6 +7737,7 @@ sweep_symbols (void)
7481 { 7737 {
7482 *sprev = sblk->next; 7738 *sprev = sblk->next;
7483 /* Unhook from the free list. */ 7739 /* Unhook from the free list. */
7740 ASAN_UNPOISON_SYMBOL (&sblk->symbols[0]);
7484 symbol_free_list = sblk->symbols[0].u.s.next; 7741 symbol_free_list = sblk->symbols[0].u.s.next;
7485 lisp_free (sblk); 7742 lisp_free (sblk);
7486 } 7743 }
@@ -7548,9 +7805,17 @@ DEFUN ("memory-info", Fmemory_info, Smemory_info, 0, 0, 0,
7548 doc: /* Return a list of (TOTAL-RAM FREE-RAM TOTAL-SWAP FREE-SWAP). 7805 doc: /* Return a list of (TOTAL-RAM FREE-RAM TOTAL-SWAP FREE-SWAP).
7549All values are in Kbytes. If there is no swap space, 7806All values are in Kbytes. If there is no swap space,
7550last two values are zero. If the system is not supported 7807last two values are zero. If the system is not supported
7551or memory information can't be obtained, return nil. */) 7808or memory information can't be obtained, return nil.
7809If `default-directory’ is remote, return memory information of the
7810respective remote host. */)
7552 (void) 7811 (void)
7553{ 7812{
7813 Lisp_Object handler
7814 = Ffind_file_name_handler (BVAR (current_buffer, directory),
7815 Qmemory_info);
7816 if (!NILP (handler))
7817 return call1 (handler, Qmemory_info);
7818
7554#if defined HAVE_LINUX_SYSINFO 7819#if defined HAVE_LINUX_SYSINFO
7555 struct sysinfo si; 7820 struct sysinfo si;
7556 uintmax_t units; 7821 uintmax_t units;
@@ -7972,6 +8237,8 @@ do hash-consing of the objects allocated to pure space. */);
7972 doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); 8237 doc: /* Non-nil means Emacs cannot get much more Lisp memory. */);
7973 Vmemory_full = Qnil; 8238 Vmemory_full = Qnil;
7974 8239
8240 DEFSYM (Qmemory_info, "memory-info");
8241
7975 DEFSYM (Qconses, "conses"); 8242 DEFSYM (Qconses, "conses");
7976 DEFSYM (Qsymbols, "symbols"); 8243 DEFSYM (Qsymbols, "symbols");
7977 DEFSYM (Qstrings, "strings"); 8244 DEFSYM (Qstrings, "strings");
diff --git a/src/buffer.c b/src/buffer.c
index ac7f4f8e9d4..38c3150f2c5 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -604,7 +604,6 @@ even if it is dead. The return value is never nil. */)
604 set_buffer_intervals (b, NULL); 604 set_buffer_intervals (b, NULL);
605 BUF_UNCHANGED_MODIFIED (b) = 1; 605 BUF_UNCHANGED_MODIFIED (b) = 1;
606 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = 1; 606 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = 1;
607 BUF_CHARS_UNCHANGED_MODIFIED (b) = 1;
608 BUF_END_UNCHANGED (b) = 0; 607 BUF_END_UNCHANGED (b) = 0;
609 BUF_BEG_UNCHANGED (b) = 0; 608 BUF_BEG_UNCHANGED (b) = 0;
610 *(BUF_GPT_ADDR (b)) = *(BUF_Z_ADDR (b)) = 0; /* Put an anchor '\0'. */ 609 *(BUF_GPT_ADDR (b)) = *(BUF_Z_ADDR (b)) = 0; /* Put an anchor '\0'. */
@@ -1748,7 +1747,19 @@ other_buffer_safely (Lisp_Object buffer)
1748 if (candidate_buffer (buf, buffer)) 1747 if (candidate_buffer (buf, buffer))
1749 return buf; 1748 return buf;
1750 1749
1751 return safe_call (1, Qget_scratch_buffer_create); 1750 /* This function must return a valid buffer, since it is frequently
1751 our last line of defense in the face of the expected buffers
1752 becoming dead under our feet. safe_call below could return nil
1753 if recreating *scratch* in Lisp, which does some fancy stuff,
1754 signals an error in some weird use case. */
1755 buf = safe_call (1, Qget_scratch_buffer_create);
1756 if (NILP (buf))
1757 {
1758 AUTO_STRING (scratch, "*scratch*");
1759 buf = Fget_buffer_create (scratch, Qnil);
1760 Fset_buffer_major_mode (buf);
1761 }
1762 return buf;
1752} 1763}
1753 1764
1754DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo, 1765DEFUN ("buffer-enable-undo", Fbuffer_enable_undo, Sbuffer_enable_undo,
@@ -3899,11 +3910,11 @@ the value is (point-min). */)
3899/* These functions are for debugging overlays. */ 3910/* These functions are for debugging overlays. */
3900 3911
3901DEFUN ("overlay-lists", Foverlay_lists, Soverlay_lists, 0, 0, 0, 3912DEFUN ("overlay-lists", Foverlay_lists, Soverlay_lists, 0, 0, 0,
3902 doc: /* Return a pair of lists giving all the overlays of the current buffer. 3913 doc: /* Return a list giving all the overlays of the current buffer.
3903The car has all the overlays before the overlay center; 3914
3904the cdr has all the overlays after the overlay center. 3915For backward compatibility, the value is actually a list that
3905Recentering overlays moves overlays between these lists. 3916holds another list; the overlays are in the inner list.
3906The lists you get are copies, so that changing them has no effect. 3917The list you get is a copy, so that changing it has no effect.
3907However, the overlays you get are the real objects that the buffer uses. */) 3918However, the overlays you get are the real objects that the buffer uses. */)
3908 (void) 3919 (void)
3909{ 3920{
@@ -3919,7 +3930,12 @@ However, the overlays you get are the real objects that the buffer uses. */)
3919DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0, 3930DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
3920 doc: /* Recenter the overlays of the current buffer around position POS. 3931 doc: /* Recenter the overlays of the current buffer around position POS.
3921That makes overlay lookup faster for positions near POS (but perhaps slower 3932That makes overlay lookup faster for positions near POS (but perhaps slower
3922for positions far away from POS). */) 3933for positions far away from POS).
3934
3935Since Emacs 29.1, this function is a no-op, because the implementation
3936of overlays changed and their lookup is now fast regardless of their
3937position in the buffer. In particular, this function no longer affects
3938the value returned by `overlay-lists'. */)
3923 (Lisp_Object pos) 3939 (Lisp_Object pos)
3924{ 3940{
3925 CHECK_FIXNUM_COERCE_MARKER (pos); 3941 CHECK_FIXNUM_COERCE_MARKER (pos);
@@ -5898,7 +5914,42 @@ this threshold.
5898If nil, these display shortcuts will always remain disabled. 5914If nil, these display shortcuts will always remain disabled.
5899 5915
5900There is no reason to change that value except for debugging purposes. */); 5916There is no reason to change that value except for debugging purposes. */);
5901 XSETFASTINT (Vlong_line_threshold, 10000); 5917 XSETFASTINT (Vlong_line_threshold, 50000);
5918
5919 DEFVAR_INT ("long-line-locked-narrowing-region-size",
5920 long_line_locked_narrowing_region_size,
5921 doc: /* Region size for locked narrowing in buffers with long lines.
5922
5923This variable has effect only in buffers which contain one or more
5924lines whose length is above `long-line-threshold', which see. For
5925performance reasons, in such buffers, low-level hooks such as
5926`fontification-functions' or `post-command-hook' are executed on a
5927narrowed buffer, with a narrowing locked with `narrowing-lock'. This
5928variable specifies the size of the narrowed region around point.
5929
5930To disable that narrowing, set this variable to 0.
5931
5932See also `long-line-locked-narrowing-bol-search-limit'.
5933
5934There is no reason to change that value except for debugging purposes. */);
5935 long_line_locked_narrowing_region_size = 500000;
5936
5937 DEFVAR_INT ("long-line-locked-narrowing-bol-search-limit",
5938 long_line_locked_narrowing_bol_search_limit,
5939 doc: /* Limit for beginning of line search in buffers with long lines.
5940
5941This variable has effect only in buffers which contain one or more
5942lines whose length is above `long-line-threshold', which see. For
5943performance reasons, in such buffers, low-level hooks such as
5944`fontification-functions' or `post-command-hook' are executed on a
5945narrowed buffer, with a narrowing locked with `narrowing-lock'. The
5946variable `long-line-locked-narrowing-region-size' specifies the size
5947of the narrowed region around point. This variable, which should be a
5948small integer, specifies the number of characters by which that region
5949can be extended backwards to make it start at the beginning of a line.
5950
5951There is no reason to change that value except for debugging purposes. */);
5952 long_line_locked_narrowing_bol_search_limit = 128;
5902 5953
5903 DEFVAR_INT ("large-hscroll-threshold", large_hscroll_threshold, 5954 DEFVAR_INT ("large-hscroll-threshold", large_hscroll_threshold,
5904 doc: /* Horizontal scroll of truncated lines above which to use redisplay shortcuts. 5955 doc: /* Horizontal scroll of truncated lines above which to use redisplay shortcuts.
diff --git a/src/buffer.h b/src/buffer.h
index dded0cd98c1..7c3d1903140 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -149,18 +149,12 @@ enum { BEG = 1, BEG_BYTE = BEG };
149#define BUF_BEG_UNCHANGED(buf) ((buf)->text->beg_unchanged) 149#define BUF_BEG_UNCHANGED(buf) ((buf)->text->beg_unchanged)
150#define BUF_END_UNCHANGED(buf) ((buf)->text->end_unchanged) 150#define BUF_END_UNCHANGED(buf) ((buf)->text->end_unchanged)
151 151
152#define BUF_CHARS_UNCHANGED_MODIFIED(buf) \
153 ((buf)->text->chars_unchanged_modified)
154
155#define UNCHANGED_MODIFIED \ 152#define UNCHANGED_MODIFIED \
156 BUF_UNCHANGED_MODIFIED (current_buffer) 153 BUF_UNCHANGED_MODIFIED (current_buffer)
157#define OVERLAY_UNCHANGED_MODIFIED \ 154#define OVERLAY_UNCHANGED_MODIFIED \
158 BUF_OVERLAY_UNCHANGED_MODIFIED (current_buffer) 155 BUF_OVERLAY_UNCHANGED_MODIFIED (current_buffer)
159#define BEG_UNCHANGED BUF_BEG_UNCHANGED (current_buffer) 156#define BEG_UNCHANGED BUF_BEG_UNCHANGED (current_buffer)
160#define END_UNCHANGED BUF_END_UNCHANGED (current_buffer) 157#define END_UNCHANGED BUF_END_UNCHANGED (current_buffer)
161
162#define CHARS_UNCHANGED_MODIFIED \
163 BUF_CHARS_UNCHANGED_MODIFIED (current_buffer)
164 158
165/* Functions to set PT in the current buffer, or another buffer. */ 159/* Functions to set PT in the current buffer, or another buffer. */
166 160
@@ -274,11 +268,6 @@ struct buffer_text
274 end_unchanged contain no useful information. */ 268 end_unchanged contain no useful information. */
275 modiff_count overlay_unchanged_modified; 269 modiff_count overlay_unchanged_modified;
276 270
277 /* CHARS_MODIFF as of last redisplay that finished. It's used
278 when we only care about changes in actual buffer text, not in
279 any other kind of changes, like properties etc. */
280 modiff_count chars_unchanged_modified;
281
282 /* Properties of this buffer's text. */ 271 /* Properties of this buffer's text. */
283 INTERVAL intervals; 272 INTERVAL intervals;
284 273
@@ -1277,8 +1266,7 @@ set_buffer_intervals (struct buffer *b, INTERVAL i)
1277INLINE bool 1266INLINE bool
1278buffer_has_overlays (void) 1267buffer_has_overlays (void)
1279{ 1268{
1280 return current_buffer->overlays 1269 return !itree_empty_p (current_buffer->overlays);
1281 && (current_buffer->overlays->root != NULL);
1282} 1270}
1283 1271
1284/* Functions for accessing a character or byte, 1272/* Functions for accessing a character or byte,
diff --git a/src/data.c b/src/data.c
index c6b85e17bc2..7ad06a9faa5 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2619,6 +2619,7 @@ bool-vector. IDX starts at 0. */)
2619 } 2619 }
2620 else if (RECORDP (array)) 2620 else if (RECORDP (array))
2621 { 2621 {
2622 CHECK_IMPURE (array, XVECTOR (array));
2622 if (idxval < 0 || idxval >= PVSIZE (array)) 2623 if (idxval < 0 || idxval >= PVSIZE (array))
2623 args_out_of_range (array, idx); 2624 args_out_of_range (array, idx);
2624 ASET (array, idxval, newelt); 2625 ASET (array, idxval, newelt);
diff --git a/src/dispextern.h b/src/dispextern.h
index 2afbdeabaab..df6134e68f0 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2342,6 +2342,14 @@ struct it
2342 optimize display. */ 2342 optimize display. */
2343 ptrdiff_t narrowed_zv; 2343 ptrdiff_t narrowed_zv;
2344 2344
2345 /* Begin position of the buffer for the locked narrowing around
2346 low-level hooks. */
2347 ptrdiff_t locked_narrowing_begv;
2348
2349 /* End position of the buffer for the locked narrowing around
2350 low-level hooks. */
2351 ptrdiff_t locked_narrowing_zv;
2352
2345 /* C string to iterate over. Non-null means get characters from 2353 /* C string to iterate over. Non-null means get characters from
2346 this string, otherwise characters are read from current_buffer 2354 this string, otherwise characters are read from current_buffer
2347 or it->string. */ 2355 or it->string. */
@@ -3405,6 +3413,8 @@ void init_iterator (struct it *, struct window *, ptrdiff_t,
3405ptrdiff_t get_narrowed_begv (struct window *, ptrdiff_t); 3413ptrdiff_t get_narrowed_begv (struct window *, ptrdiff_t);
3406ptrdiff_t get_narrowed_zv (struct window *, ptrdiff_t); 3414ptrdiff_t get_narrowed_zv (struct window *, ptrdiff_t);
3407ptrdiff_t get_closer_narrowed_begv (struct window *, ptrdiff_t); 3415ptrdiff_t get_closer_narrowed_begv (struct window *, ptrdiff_t);
3416ptrdiff_t get_locked_narrowing_begv (ptrdiff_t);
3417ptrdiff_t get_locked_narrowing_zv (ptrdiff_t);
3408void init_iterator_to_row_start (struct it *, struct window *, 3418void init_iterator_to_row_start (struct it *, struct window *,
3409 struct glyph_row *); 3419 struct glyph_row *);
3410void start_display (struct it *, struct window *, struct text_pos); 3420void start_display (struct it *, struct window *, struct text_pos);
diff --git a/src/editfns.c b/src/editfns.c
index 17dca4708ed..8d56ef21d90 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2653,88 +2653,216 @@ DEFUN ("delete-and-extract-region", Fdelete_and_extract_region,
2653 return del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1); 2653 return del_range_1 (XFIXNUM (start), XFIXNUM (end), 1, 1);
2654} 2654}
2655 2655
2656DEFUN ("widen", Fwiden, Swiden, 0, 0, "", 2656/* Alist of buffers in which locked narrowing is used. The car of
2657 doc: /* Remove restrictions (narrowing) from current buffer. 2657 each list element is a buffer, the cdr is a list of triplets (tag
2658This allows the buffer's full text to be seen and edited. 2658 begv-marker zv-marker). The last element of that list always uses
2659 the (uninterned) Qoutermost_narrowing tag and records the narrowing
2660 bounds that were set by the user and that are visible on display.
2661 This alist is used internally by narrow-to-region, widen,
2662 narrowing-lock, narrowing-unlock and save-restriction. */
2663static Lisp_Object narrowing_locks;
2664
2665/* Add BUF with its LOCKS in the narrowing_locks alist. */
2666static void
2667narrowing_locks_add (Lisp_Object buf, Lisp_Object locks)
2668{
2669 narrowing_locks = nconc2 (list1 (list2 (buf, locks)), narrowing_locks);
2670}
2659 2671
2660Note that, when the current buffer contains one or more lines whose 2672/* Remove BUF and its locks from the narrowing_locks alist. Do
2661length is above `long-line-threshold', Emacs may decide to leave, for 2673 nothing if BUF is not present in narrowing_locks. */
2662performance reasons, the accessible portion of the buffer unchanged 2674static void
2663after this function is called from low-level hooks, such as 2675narrowing_locks_remove (Lisp_Object buf)
2664`jit-lock-functions' or `post-command-hook'. */) 2676{
2665 (void) 2677 narrowing_locks = Fdelq (Fassoc (buf, narrowing_locks, Qnil),
2678 narrowing_locks);
2679}
2680
2681/* Retrieve one of the BEGV/ZV bounds of a narrowing in BUF from the
2682 narrowing_locks alist, as a pointer to a struct Lisp_Marker, or
2683 NULL if BUF is not in narrowing_locks or is a killed buffer. When
2684 OUTERMOST is true, the bounds that were set by the user and that
2685 are visible on display are returned. Otherwise the innermost
2686 locked narrowing bounds are returned. */
2687static struct Lisp_Marker *
2688narrowing_lock_get_bound (Lisp_Object buf, bool begv, bool outermost)
2689{
2690 if (NILP (Fbuffer_live_p (buf)))
2691 return NULL;
2692 Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
2693 if (NILP (buffer_locks))
2694 return NULL;
2695 buffer_locks = XCAR (XCDR (buffer_locks));
2696 Lisp_Object bounds
2697 = outermost
2698 ? XCDR (assq_no_quit (Qoutermost_narrowing, buffer_locks))
2699 : XCDR (XCAR (buffer_locks));
2700 eassert (! NILP (bounds));
2701 Lisp_Object marker = begv ? XCAR (bounds) : XCAR (XCDR (bounds));
2702 eassert (EQ (Fmarker_buffer (marker), buf));
2703 return XMARKER (marker);
2704}
2705
2706/* Retrieve the tag of the innermost narrowing in BUF. Return nil if
2707 BUF is not in narrowing_locks or is a killed buffer. */
2708static Lisp_Object
2709narrowing_lock_peek_tag (Lisp_Object buf)
2666{ 2710{
2667 if (! NILP (Vrestrictions_locked)) 2711 if (NILP (Fbuffer_live_p (buf)))
2668 return Qnil; 2712 return Qnil;
2669 if (BEG != BEGV || Z != ZV) 2713 Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
2670 current_buffer->clip_changed = 1; 2714 if (NILP (buffer_locks))
2671 BEGV = BEG; 2715 return Qnil;
2672 BEGV_BYTE = BEG_BYTE; 2716 Lisp_Object tag = XCAR (XCAR (XCAR (XCDR (buffer_locks))));
2673 SET_BUF_ZV_BOTH (current_buffer, Z, Z_BYTE); 2717 eassert (! NILP (tag));
2674 /* Changing the buffer bounds invalidates any recorded current column. */ 2718 return tag;
2675 invalidate_current_column ();
2676 return Qnil;
2677} 2719}
2678 2720
2721/* Add a LOCK for BUF in the narrowing_locks alist. */
2679static void 2722static void
2680unwind_locked_begv (Lisp_Object point_min) 2723narrowing_lock_push (Lisp_Object buf, Lisp_Object lock)
2681{ 2724{
2682 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min)); 2725 Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
2726 if (NILP (buffer_locks))
2727 narrowing_locks_add (buf, list1 (lock));
2728 else
2729 XSETCDR (buffer_locks, list1 (nconc2 (list1 (lock),
2730 XCAR (XCDR (buffer_locks)))));
2683} 2731}
2684 2732
2733/* Remove the innermost lock in BUF from the narrowing_locks alist.
2734 Do nothing if BUF is not present in narrowing_locks. */
2685static void 2735static void
2686unwind_locked_zv (Lisp_Object point_max) 2736narrowing_lock_pop (Lisp_Object buf)
2687{ 2737{
2688 SET_BUF_ZV (current_buffer, XFIXNUM (point_max)); 2738 Lisp_Object buffer_locks = assq_no_quit (buf, narrowing_locks);
2739 if (NILP (buffer_locks))
2740 return;
2741 if (EQ (narrowing_lock_peek_tag (buf), Qoutermost_narrowing))
2742 narrowing_locks_remove (buf);
2743 else
2744 XSETCDR (buffer_locks, list1 (XCDR (XCAR (XCDR (buffer_locks)))));
2689} 2745}
2690 2746
2691/* Internal function for Fnarrow_to_region, meant to be used with a 2747static void
2692 third argument 'true', in which case it should be followed by "specbind 2748unwind_reset_outermost_narrowing (Lisp_Object buf)
2693 (Qrestrictions_locked, Qt)". */
2694Lisp_Object
2695narrow_to_region_internal (Lisp_Object start, Lisp_Object end, bool lock)
2696{ 2749{
2697 EMACS_INT s = fix_position (start), e = fix_position (end); 2750 struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
2698 2751 struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
2699 if (e < s) 2752 if (begv != NULL && zv != NULL)
2700 { 2753 {
2701 EMACS_INT tem = s; s = e; e = tem; 2754 SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
2755 SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
2702 } 2756 }
2757 else
2758 narrowing_locks_remove (buf);
2759}
2703 2760
2704 if (lock) 2761/* Restore the narrowing bounds that were set by the user, and restore
2762 the bounds of the locked narrowing upon return.
2763 In particular, this function is called when redisplay starts, so
2764 that if a Lisp function executed during redisplay calls (redisplay)
2765 while a locked narrowing is in effect, the locked narrowing will
2766 not be visible on display. */
2767void
2768reset_outermost_narrowings (void)
2769{
2770 Lisp_Object val, buf;
2771 for (val = narrowing_locks; CONSP (val); val = XCDR (val))
2705 { 2772 {
2706 if (!(BEGV <= s && s <= e && e <= ZV)) 2773 buf = XCAR (XCAR (val));
2707 args_out_of_range (start, end); 2774 eassert (BUFFERP (buf));
2775 struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, true);
2776 struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, true);
2777 if (begv != NULL && zv != NULL)
2778 {
2779 SET_BUF_BEGV_BOTH (XBUFFER (buf), begv->charpos, begv->bytepos);
2780 SET_BUF_ZV_BOTH (XBUFFER (buf), zv->charpos, zv->bytepos);
2781 record_unwind_protect (unwind_reset_outermost_narrowing, buf);
2782 }
2783 else
2784 narrowing_locks_remove (buf);
2785 }
2786}
2708 2787
2709 if (BEGV != s || ZV != e) 2788/* Helper functions to save and restore the narrowing locks of the
2710 current_buffer->clip_changed = 1; 2789 current buffer in Fsave_restriction. */
2790static Lisp_Object
2791narrowing_locks_save (void)
2792{
2793 Lisp_Object buf = Fcurrent_buffer ();
2794 Lisp_Object locks = assq_no_quit (buf, narrowing_locks);
2795 if (NILP (locks))
2796 return Qnil;
2797 locks = XCAR (XCDR (locks));
2798 return Fcons (buf, Fcopy_sequence (locks));
2799}
2711 2800
2712 record_unwind_protect (restore_point_unwind, Fpoint_marker ()); 2801static void
2713 record_unwind_protect (unwind_locked_begv, Fpoint_min ()); 2802narrowing_locks_restore (Lisp_Object buf_and_saved_locks)
2714 record_unwind_protect (unwind_locked_zv, Fpoint_max ()); 2803{
2804 if (NILP (buf_and_saved_locks))
2805 return;
2806 Lisp_Object buf = XCAR (buf_and_saved_locks);
2807 Lisp_Object saved_locks = XCDR (buf_and_saved_locks);
2808 narrowing_locks_remove (buf);
2809 narrowing_locks_add (buf, saved_locks);
2810}
2715 2811
2716 SET_BUF_BEGV (current_buffer, s); 2812static void
2717 SET_BUF_ZV (current_buffer, e); 2813unwind_narrow_to_region_locked (Lisp_Object tag)
2814{
2815 Fnarrowing_unlock (tag);
2816 Fwiden ();
2817}
2818
2819/* Narrow current_buffer to BEGV-ZV with a narrowing locked with TAG. */
2820void
2821narrow_to_region_locked (Lisp_Object begv, Lisp_Object zv, Lisp_Object tag)
2822{
2823 Fnarrow_to_region (begv, zv);
2824 Fnarrowing_lock (tag);
2825 record_unwind_protect (restore_point_unwind, Fpoint_marker ());
2826 record_unwind_protect (unwind_narrow_to_region_locked, tag);
2827}
2828
2829DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
2830 doc: /* Remove restrictions (narrowing) from current buffer.
2831
2832This allows the buffer's full text to be seen and edited, unless
2833restrictions have been locked with `narrowing-lock', which see, in
2834which case the narrowing that was current when `narrowing-lock' was
2835called is restored. */)
2836 (void)
2837{
2838 Fset (Qoutermost_narrowing, Qnil);
2839 Lisp_Object buf = Fcurrent_buffer ();
2840 Lisp_Object tag = narrowing_lock_peek_tag (buf);
2841
2842 if (NILP (tag))
2843 {
2844 if (BEG != BEGV || Z != ZV)
2845 current_buffer->clip_changed = 1;
2846 BEGV = BEG;
2847 BEGV_BYTE = BEG_BYTE;
2848 SET_BUF_ZV_BOTH (current_buffer, Z, Z_BYTE);
2718 } 2849 }
2719 else 2850 else
2720 { 2851 {
2721 if (! NILP (Vrestrictions_locked)) 2852 struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
2722 return Qnil; 2853 struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
2723 2854 eassert (begv != NULL && zv != NULL);
2724 if (!(BEG <= s && s <= e && e <= Z)) 2855 if (begv->charpos != BEGV || zv->charpos != ZV)
2725 args_out_of_range (start, end);
2726
2727 if (BEGV != s || ZV != e)
2728 current_buffer->clip_changed = 1; 2856 current_buffer->clip_changed = 1;
2729 2857 SET_BUF_BEGV_BOTH (current_buffer, begv->charpos, begv->bytepos);
2730 SET_BUF_BEGV (current_buffer, s); 2858 SET_BUF_ZV_BOTH (current_buffer, zv->charpos, zv->bytepos);
2731 SET_BUF_ZV (current_buffer, e); 2859 /* If the only remaining bounds in narrowing_locks for
2860 current_buffer are the bounds that were set by the user, no
2861 locked narrowing is in effect in current_buffer anymore:
2862 remove it from the narrowing_locks alist. */
2863 if (EQ (tag, Qoutermost_narrowing))
2864 narrowing_lock_pop (buf);
2732 } 2865 }
2733
2734 if (PT < s)
2735 SET_PT (s);
2736 if (e < PT)
2737 SET_PT (e);
2738 /* Changing the buffer bounds invalidates any recorded current column. */ 2866 /* Changing the buffer bounds invalidates any recorded current column. */
2739 invalidate_current_column (); 2867 invalidate_current_column ();
2740 return Qnil; 2868 return Qnil;
@@ -2751,14 +2879,110 @@ When calling from Lisp, pass two arguments START and END:
2751positions (integers or markers) bounding the text that should 2879positions (integers or markers) bounding the text that should
2752remain visible. 2880remain visible.
2753 2881
2754Note that, when the current buffer contains one or more lines whose 2882When restrictions have been locked with `narrowing-lock', which see,
2755length is above `long-line-threshold', Emacs may decide to leave, for 2883`narrow-to-region' can be used only within the limits of the
2756performance reasons, the accessible portion of the buffer unchanged 2884restrictions that were current when `narrowing-lock' was called. If
2757after this function is called from low-level hooks, such as 2885the START or END arguments are outside these limits, the corresponding
2758`jit-lock-functions' or `post-command-hook'. */) 2886limit of the locked restriction is used instead of the argument. */)
2759 (Lisp_Object start, Lisp_Object end) 2887 (Lisp_Object start, Lisp_Object end)
2760{ 2888{
2761 return narrow_to_region_internal (start, end, false); 2889 EMACS_INT s = fix_position (start), e = fix_position (end);
2890
2891 if (e < s)
2892 {
2893 EMACS_INT tem = s; s = e; e = tem;
2894 }
2895
2896 if (!(BEG <= s && s <= e && e <= Z))
2897 args_out_of_range (start, end);
2898
2899 Lisp_Object buf = Fcurrent_buffer ();
2900 if (! NILP (narrowing_lock_peek_tag (buf)))
2901 {
2902 struct Lisp_Marker *begv = narrowing_lock_get_bound (buf, true, false);
2903 struct Lisp_Marker *zv = narrowing_lock_get_bound (buf, false, false);
2904 eassert (begv != NULL && zv != NULL);
2905 /* Limit the start and end positions to those of the locked
2906 narrowing. */
2907 if (s < begv->charpos) s = begv->charpos;
2908 if (s > zv->charpos) s = zv->charpos;
2909 if (e < begv->charpos) e = begv->charpos;
2910 if (e > zv->charpos) e = zv->charpos;
2911 }
2912
2913 /* Record the accessible range of the buffer when narrow-to-region
2914 is called, that is, before applying the narrowing. It is used
2915 only by narrowing-lock. */
2916 Fset (Qoutermost_narrowing, list3 (Qoutermost_narrowing,
2917 Fpoint_min_marker (),
2918 Fpoint_max_marker ()));
2919
2920 if (BEGV != s || ZV != e)
2921 current_buffer->clip_changed = 1;
2922
2923 SET_BUF_BEGV (current_buffer, s);
2924 SET_BUF_ZV (current_buffer, e);
2925
2926 if (PT < s)
2927 SET_PT (s);
2928 if (e < PT)
2929 SET_PT (e);
2930 /* Changing the buffer bounds invalidates any recorded current column. */
2931 invalidate_current_column ();
2932 return Qnil;
2933}
2934
2935DEFUN ("narrowing-lock", Fnarrowing_lock, Snarrowing_lock, 1, 1, 0,
2936 doc: /* Lock the current narrowing with TAG.
2937
2938When restrictions are locked, `narrow-to-region' and `widen' can be
2939used only within the limits of the restrictions that were current when
2940`narrowing-lock' was called, unless the lock is removed by calling
2941`narrowing-unlock' with TAG.
2942
2943Locking restrictions should be used sparingly, after carefully
2944considering the potential adverse effects on the code that will be
2945executed within locked restrictions. It is typically meant to be used
2946around portions of code that would become too slow, and make Emacs
2947unresponsive, if they were executed in a large buffer. For example,
2948restrictions are locked by Emacs around low-level hooks such as
2949`fontification-functions' or `post-command-hook'.
2950
2951Locked restrictions are never visible on display, and can therefore
2952not be used as a stronger variant of normal restrictions. */)
2953 (Lisp_Object tag)
2954{
2955 Lisp_Object buf = Fcurrent_buffer ();
2956 Lisp_Object outermost_narrowing
2957 = buffer_local_value (Qoutermost_narrowing, buf);
2958 /* If narrowing-lock is called without being preceded by
2959 narrow-to-region, do nothing. */
2960 if (NILP (outermost_narrowing))
2961 return Qnil;
2962 if (NILP (narrowing_lock_peek_tag (buf)))
2963 narrowing_lock_push (buf, outermost_narrowing);
2964 narrowing_lock_push (buf, list3 (tag,
2965 Fpoint_min_marker (),
2966 Fpoint_max_marker ()));
2967 return Qnil;
2968}
2969
2970DEFUN ("narrowing-unlock", Fnarrowing_unlock, Snarrowing_unlock, 1, 1, 0,
2971 doc: /* Unlock a narrowing locked with (narrowing-lock TAG).
2972
2973Unlocking restrictions locked with `narrowing-lock' should be used
2974sparingly, after carefully considering the reasons why restrictions
2975were locked. Restrictions are typically locked around portions of
2976code that would become too slow, and make Emacs unresponsive, if they
2977were executed in a large buffer. For example, restrictions are locked
2978by Emacs around low-level hooks such as `fontification-functions' or
2979`post-command-hook'. */)
2980 (Lisp_Object tag)
2981{
2982 Lisp_Object buf = Fcurrent_buffer ();
2983 if (EQ (narrowing_lock_peek_tag (buf), tag))
2984 narrowing_lock_pop (buf);
2985 return Qnil;
2762} 2986}
2763 2987
2764Lisp_Object 2988Lisp_Object
@@ -2858,11 +3082,12 @@ DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 0
2858 doc: /* Execute BODY, saving and restoring current buffer's restrictions. 3082 doc: /* Execute BODY, saving and restoring current buffer's restrictions.
2859The buffer's restrictions make parts of the beginning and end invisible. 3083The buffer's restrictions make parts of the beginning and end invisible.
2860\(They are set up with `narrow-to-region' and eliminated with `widen'.) 3084\(They are set up with `narrow-to-region' and eliminated with `widen'.)
2861This special form, `save-restriction', saves the current buffer's restrictions 3085This special form, `save-restriction', saves the current buffer's
2862when it is entered, and restores them when it is exited. 3086restrictions, as well as their locks if they have been locked with
3087`narrowing-lock', when it is entered, and restores them when it is exited.
2863So any `narrow-to-region' within BODY lasts only until the end of the form. 3088So any `narrow-to-region' within BODY lasts only until the end of the form.
2864The old restrictions settings are restored 3089The old restrictions settings are restored even in case of abnormal exit
2865even in case of abnormal exit (throw or error). 3090\(throw or error).
2866 3091
2867The value returned is the value of the last form in BODY. 3092The value returned is the value of the last form in BODY.
2868 3093
@@ -2877,6 +3102,7 @@ usage: (save-restriction &rest BODY) */)
2877 specpdl_ref count = SPECPDL_INDEX (); 3102 specpdl_ref count = SPECPDL_INDEX ();
2878 3103
2879 record_unwind_protect (save_restriction_restore, save_restriction_save ()); 3104 record_unwind_protect (save_restriction_restore, save_restriction_save ());
3105 record_unwind_protect (narrowing_locks_restore, narrowing_locks_save ());
2880 val = Fprogn (body); 3106 val = Fprogn (body);
2881 return unbind_to (count, val); 3107 return unbind_to (count, val);
2882} 3108}
@@ -3053,18 +3279,18 @@ The other arguments are substituted into it to make the result, a string.
3053The format control string may contain %-sequences meaning to substitute 3279The format control string may contain %-sequences meaning to substitute
3054the next available argument, or the argument explicitly specified: 3280the next available argument, or the argument explicitly specified:
3055 3281
3056%s means print a string argument. Actually, prints any object, with `princ'. 3282%s means produce a string argument. Actually, produces any object with `princ'.
3057%d means print as signed number in decimal. 3283%d means produce as signed number in decimal.
3058%o means print a number in octal. 3284%o means produce a number in octal.
3059%x means print a number in hex. 3285%x means produce a number in hex.
3060%X is like %x, but uses upper case. 3286%X is like %x, but uses upper case.
3061%e means print a number in exponential notation. 3287%e means produce a number in exponential notation.
3062%f means print a number in decimal-point notation. 3288%f means produce a number in decimal-point notation.
3063%g means print a number in exponential notation if the exponent would be 3289%g means produce a number in exponential notation if the exponent would be
3064 less than -4 or greater than or equal to the precision (default: 6); 3290 less than -4 or greater than or equal to the precision (default: 6);
3065 otherwise it prints in decimal-point notation. 3291 otherwise it produces in decimal-point notation.
3066%c means print a number as a single character. 3292%c means produce a number as a single character.
3067%S means print any object as an s-expression (using `prin1'). 3293%S means produce any object as an s-expression (using `prin1').
3068 3294
3069The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. 3295The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.
3070%o, %x, and %X treat arguments as unsigned if `binary-as-unsigned' is t 3296%o, %x, and %X treat arguments as unsigned if `binary-as-unsigned' is t
@@ -3099,7 +3325,7 @@ included even if the precision is zero, and also forces trailing
3099zeros after the decimal point to be left in place. 3325zeros after the decimal point to be left in place.
3100 3326
3101The width specifier supplies a lower limit for the length of the 3327The width specifier supplies a lower limit for the length of the
3102printed representation. The padding, if any, normally goes on the 3328produced representation. The padding, if any, normally goes on the
3103left, but it goes on the right if the - flag is present. The padding 3329left, but it goes on the right if the - flag is present. The padding
3104character is normally a space, but it is 0 if the 0 flag is present. 3330character is normally a space, but it is 0 if the 0 flag is present.
3105The 0 flag is ignored if the - flag is present, or the format sequence 3331The 0 flag is ignored if the - flag is present, or the format sequence
@@ -3108,7 +3334,7 @@ is something other than %d, %o, %x, %e, %f, and %g.
3108For %e and %f sequences, the number after the "." in the precision 3334For %e and %f sequences, the number after the "." in the precision
3109specifier says how many decimal places to show; if zero, the decimal 3335specifier says how many decimal places to show; if zero, the decimal
3110point itself is omitted. For %g, the precision specifies how many 3336point itself is omitted. For %g, the precision specifies how many
3111significant digits to print; zero or omitted are treated as 1. 3337significant digits to produce; zero or omitted are treated as 1.
3112For %s and %S, the precision specifier truncates the string to the 3338For %s and %S, the precision specifier truncates the string to the
3113given width. 3339given width.
3114 3340
@@ -4518,6 +4744,8 @@ syms_of_editfns (void)
4518 DEFSYM (Qwall, "wall"); 4744 DEFSYM (Qwall, "wall");
4519 DEFSYM (Qpropertize, "propertize"); 4745 DEFSYM (Qpropertize, "propertize");
4520 4746
4747 staticpro (&narrowing_locks);
4748
4521 DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion, 4749 DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
4522 doc: /* Non-nil means text motion commands don't notice fields. */); 4750 doc: /* Non-nil means text motion commands don't notice fields. */);
4523 Vinhibit_field_text_motion = Qnil; 4751 Vinhibit_field_text_motion = Qnil;
@@ -4577,11 +4805,12 @@ This variable is experimental; email 32252@debbugs.gnu.org if you need
4577it to be non-nil. */); 4805it to be non-nil. */);
4578 binary_as_unsigned = false; 4806 binary_as_unsigned = false;
4579 4807
4580 DEFSYM (Qrestrictions_locked, "restrictions-locked"); 4808 DEFVAR_LISP ("outermost-narrowing", Voutermost_narrowing,
4581 DEFVAR_LISP ("restrictions-locked", Vrestrictions_locked, 4809 doc: /* Outermost narrowing bounds, if any. Internal use only. */);
4582 doc: /* If non-nil, restrictions are currently locked. */); 4810 Voutermost_narrowing = Qnil;
4583 Vrestrictions_locked = Qnil; 4811 Fmake_variable_buffer_local (Qoutermost_narrowing);
4584 Funintern (Qrestrictions_locked, Qnil); 4812 DEFSYM (Qoutermost_narrowing, "outermost-narrowing");
4813 Funintern (Qoutermost_narrowing, Qnil);
4585 4814
4586 defsubr (&Spropertize); 4815 defsubr (&Spropertize);
4587 defsubr (&Schar_equal); 4816 defsubr (&Schar_equal);
@@ -4674,6 +4903,8 @@ it to be non-nil. */);
4674 defsubr (&Sdelete_and_extract_region); 4903 defsubr (&Sdelete_and_extract_region);
4675 defsubr (&Swiden); 4904 defsubr (&Swiden);
4676 defsubr (&Snarrow_to_region); 4905 defsubr (&Snarrow_to_region);
4906 defsubr (&Snarrowing_lock);
4907 defsubr (&Snarrowing_unlock);
4677 defsubr (&Ssave_restriction); 4908 defsubr (&Ssave_restriction);
4678 defsubr (&Stranspose_regions); 4909 defsubr (&Stranspose_regions);
4679} 4910}
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
index bef89b059fc..d485de5aa18 100644
--- a/src/emacs-module.h.in
+++ b/src/emacs-module.h.in
@@ -183,6 +183,21 @@ struct emacs_env_29
183@module_env_snippet_29@ 183@module_env_snippet_29@
184}; 184};
185 185
186struct emacs_env_30
187{
188@module_env_snippet_25@
189
190@module_env_snippet_26@
191
192@module_env_snippet_27@
193
194@module_env_snippet_28@
195
196@module_env_snippet_29@
197
198@module_env_snippet_30@
199};
200
186/* Every module should define a function as follows. */ 201/* Every module should define a function as follows. */
187extern int emacs_module_init (struct emacs_runtime *runtime) 202extern int emacs_module_init (struct emacs_runtime *runtime)
188 EMACS_NOEXCEPT 203 EMACS_NOEXCEPT
diff --git a/src/emacs.c b/src/emacs.c
index 105539aa192..d8a2863fd9c 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -295,6 +295,7 @@ Initialization options:\n\
295--no-site-lisp, -nsl do not add site-lisp directories to load-path\n\ 295--no-site-lisp, -nsl do not add site-lisp directories to load-path\n\
296--no-splash do not display a splash screen on startup\n\ 296--no-splash do not display a splash screen on startup\n\
297--no-window-system, -nw do not communicate with X, ignoring $DISPLAY\n\ 297--no-window-system, -nw do not communicate with X, ignoring $DISPLAY\n\
298--init-directory=DIR use DIR when looking for the Emacs init files.\n\
298", 299",
299 "\ 300 "\
300--quick, -Q equivalent to:\n\ 301--quick, -Q equivalent to:\n\
@@ -1923,6 +1924,12 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1923 Vcoding_system_hash_table. */ 1924 Vcoding_system_hash_table. */
1924 syms_of_coding (); /* This should be after syms_of_fileio. */ 1925 syms_of_coding (); /* This should be after syms_of_fileio. */
1925 init_frame_once (); /* Before init_window_once. */ 1926 init_frame_once (); /* Before init_window_once. */
1927 /* init_window_once calls make_initial_frame, which calls
1928 Fcurrent_time and bset_display_time, both of which allocate
1929 bignums. Without the following call to init_bignums, crashes
1930 happen on Windows 9X after dumping when GC tries to free a
1931 pointer allocated on the system heap. */
1932 init_bignum ();
1926 init_window_once (); /* Init the window system. */ 1933 init_window_once (); /* Init the window system. */
1927#ifdef HAVE_WINDOW_SYSTEM 1934#ifdef HAVE_WINDOW_SYSTEM
1928 init_fringe_once (); /* Swap bitmaps if necessary. */ 1935 init_fringe_once (); /* Swap bitmaps if necessary. */
diff --git a/src/fileio.c b/src/fileio.c
index 92335b639cd..e7c2af81421 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -134,6 +134,7 @@ static dev_t timestamp_file_system;
134 is added here. */ 134 is added here. */
135static Lisp_Object Vwrite_region_annotation_buffers; 135static Lisp_Object Vwrite_region_annotation_buffers;
136 136
137static Lisp_Object emacs_readlinkat (int, char const *);
137static Lisp_Object file_name_directory (Lisp_Object); 138static Lisp_Object file_name_directory (Lisp_Object);
138static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, 139static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
139 Lisp_Object *, struct coding_system *); 140 Lisp_Object *, struct coding_system *);
@@ -2219,7 +2220,7 @@ permissions. */)
2219 report_file_error ("Copying permissions to", newname); 2220 report_file_error ("Copying permissions to", newname);
2220 } 2221 }
2221#else /* not WINDOWSNT */ 2222#else /* not WINDOWSNT */
2222 ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0); 2223 ifd = emacs_open (SSDATA (encoded_file), O_RDONLY | O_NONBLOCK, 0);
2223 2224
2224 if (ifd < 0) 2225 if (ifd < 0)
2225 report_file_error ("Opening input file", file); 2226 report_file_error ("Opening input file", file);
@@ -2427,16 +2428,11 @@ DEFUN ("make-directory-internal", Fmake_directory_internal,
2427 (Lisp_Object directory) 2428 (Lisp_Object directory)
2428{ 2429{
2429 const char *dir; 2430 const char *dir;
2430 Lisp_Object handler;
2431 Lisp_Object encoded_dir; 2431 Lisp_Object encoded_dir;
2432 2432
2433 CHECK_STRING (directory); 2433 CHECK_STRING (directory);
2434 directory = Fexpand_file_name (directory, Qnil); 2434 directory = Fexpand_file_name (directory, Qnil);
2435 2435
2436 handler = Ffind_file_name_handler (directory, Qmake_directory_internal);
2437 if (!NILP (handler))
2438 return call2 (handler, Qmake_directory_internal, directory);
2439
2440 encoded_dir = ENCODE_FILE (directory); 2436 encoded_dir = ENCODE_FILE (directory);
2441 2437
2442 dir = SSDATA (encoded_dir); 2438 dir = SSDATA (encoded_dir);
@@ -2710,31 +2706,19 @@ This is what happens in interactive use with M-x. */)
2710 } 2706 }
2711 if (dirp) 2707 if (dirp)
2712 call4 (Qcopy_directory, file, newname, Qt, Qnil); 2708 call4 (Qcopy_directory, file, newname, Qt, Qnil);
2713 else 2709 else if (S_ISREG (file_st.st_mode))
2714 { 2710 Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt);
2715 Lisp_Object symlink_target 2711 else if (S_ISLNK (file_st.st_mode))
2716 = (S_ISLNK (file_st.st_mode) 2712 {
2717 ? check_emacs_readlinkat (AT_FDCWD, file, SSDATA (encoded_file)) 2713 Lisp_Object target = emacs_readlinkat (AT_FDCWD,
2718 : Qnil); 2714 SSDATA (encoded_file));
2719 if (!NILP (symlink_target)) 2715 if (!NILP (target))
2720 Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); 2716 Fmake_symbolic_link (target, newname, ok_if_already_exists);
2721 else if (S_ISFIFO (file_st.st_mode))
2722 {
2723 /* If it's a FIFO, calling `copy-file' will hang if it's a
2724 inter-file system move, so do it here. (It will signal
2725 an error in that case, but it won't hang in any case.) */
2726 if (!NILP (ok_if_already_exists))
2727 barf_or_query_if_file_exists (newname, false,
2728 "rename to it",
2729 FIXNUMP (ok_if_already_exists),
2730 false);
2731 if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) != 0)
2732 report_file_errno ("Renaming", list2 (file, newname), errno);
2733 return Qnil;
2734 }
2735 else 2717 else
2736 Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt); 2718 report_file_error ("Renaming", list2 (file, newname));
2737 } 2719 }
2720 else
2721 report_file_errno ("Renaming", list2 (file, newname), rename_errno);
2738 2722
2739 specpdl_ref count = SPECPDL_INDEX (); 2723 specpdl_ref count = SPECPDL_INDEX ();
2740 specbind (Qdelete_by_moving_to_trash, Qnil); 2724 specbind (Qdelete_by_moving_to_trash, Qnil);
diff --git a/src/fns.c b/src/fns.c
index 7cc6d00afef..eeb65cadf3f 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -334,7 +334,9 @@ Letter-case is significant, but text properties are ignored. */)
334DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0, 334DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
335 doc: /* Return t if two strings have identical contents. 335 doc: /* Return t if two strings have identical contents.
336Case is significant, but text properties are ignored. 336Case is significant, but text properties are ignored.
337Symbols are also allowed; their print names are used instead. */) 337Symbols are also allowed; their print names are used instead.
338
339See also `string-equal-ignore-case'. */)
338 (register Lisp_Object s1, Lisp_Object s2) 340 (register Lisp_Object s1, Lisp_Object s2)
339{ 341{
340 if (SYMBOLP (s1)) 342 if (SYMBOLP (s1))
@@ -495,8 +497,13 @@ Symbols are also allowed; their print names are used instead. */)
495 int ws = sizeof (word_t); 497 int ws = sizeof (word_t);
496 const word_t *w1 = (const word_t *) SDATA (string1); 498 const word_t *w1 = (const word_t *) SDATA (string1);
497 const word_t *w2 = (const word_t *) SDATA (string2); 499 const word_t *w2 = (const word_t *) SDATA (string2);
498 while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws]) 500 while (b < nb - ws + 1)
499 b += ws; 501 {
502 if (UNALIGNED_LOAD_SIZE (w1, b / ws)
503 != UNALIGNED_LOAD_SIZE (w2, b / ws))
504 break;
505 b += ws;
506 }
500 } 507 }
501 508
502 /* Scan forward to the differing byte. */ 509 /* Scan forward to the differing byte. */
@@ -3936,7 +3943,7 @@ system.
3936If the region can't be decoded, signal an error and don't modify the buffer. 3943If the region can't be decoded, signal an error and don't modify the buffer.
3937Optional third argument BASE64URL determines whether to use the URL variant 3944Optional third argument BASE64URL determines whether to use the URL variant
3938of the base 64 encoding, as defined in RFC 4648. 3945of the base 64 encoding, as defined in RFC 4648.
3939If optional fourth argument INGORE-INVALID is non-nil invalid characters 3946If optional fourth argument IGNORE-INVALID is non-nil invalid characters
3940are ignored instead of signaling an error. */) 3947are ignored instead of signaling an error. */)
3941 (Lisp_Object beg, Lisp_Object end, Lisp_Object base64url, 3948 (Lisp_Object beg, Lisp_Object end, Lisp_Object base64url,
3942 Lisp_Object ignore_invalid) 3949 Lisp_Object ignore_invalid)
diff --git a/src/frame.c b/src/frame.c
index b57b296be54..7d902dabd4f 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1892,12 +1892,61 @@ other_frames (struct frame *f, bool invisible, bool force)
1892 1892
1893 if (f != f1) 1893 if (f != f1)
1894 { 1894 {
1895 /* The following code is defined out because it is
1896 responsible for a performance drop under X connections
1897 over a network, and its purpose is unclear. XSync does
1898 not handle events (or call any callbacks defined by
1899 Emacs), and as such it should not note any "recent change
1900 in visibility".
1901
1902 When writing new code, please try as hard as possible to
1903 avoid calls that require a roundtrip to the X server.
1904 When such calls are inevitable, use the XCB library to
1905 handle multiple consecutive requests with a data reply in
1906 a more asynchronous fashion. The following code
1907 demonstrates why:
1908
1909 rc = XGetWindowProperty (dpyinfo->display, window, ...
1910 status = XGrabKeyboard (dpyinfo->display, ...
1911
1912 here, `XGetWindowProperty' will wait for a reply from the
1913 X server before returning, and thus allowing Emacs to
1914 make the XGrabKeyboard request, which in itself also
1915 requires waiting a reply. When XCB is available, this
1916 code could be written:
1917
1918#ifdef HAVE_XCB
1919 xcb_get_property_cookie_t cookie1;
1920 xcb_get_property_reply_t *reply1;
1921 xcb_grab_keyboard_cookie_t cookie2;
1922 xcb_grab_keyboard_reply_t *reply2;
1923
1924 cookie1 = xcb_get_property (dpyinfo->xcb_connection, window, ...
1925 cookie2 = xcb_grab_keyboard (dpyinfo->xcb_connection, ...
1926 reply1 = xcb_get_property_reply (dpyinfo->xcb_connection,
1927 cookie1);
1928 reply2 = xcb_grab_keyboard_reply (dpyinfo->xcb_connection,
1929 cookie2);
1930#endif
1931
1932 In this code, the GetProperty and GrabKeyboard requests
1933 are made simultaneously, and replies are then obtained
1934 from the server at once, avoiding the extraneous
1935 roundtrip to the X server after the call to
1936 `XGetWindowProperty'.
1937
1938 However, please keep an alternative implementation
1939 available for use when Emacs is built without XCB. */
1940
1941#if 0
1895 /* Verify that we can still talk to the frame's X window, and 1942 /* Verify that we can still talk to the frame's X window, and
1896 note any recent change in visibility. */ 1943 note any recent change in visibility. */
1897#ifdef HAVE_X_WINDOWS 1944#ifdef HAVE_X_WINDOWS
1898 if (FRAME_WINDOW_P (f1)) 1945 if (FRAME_WINDOW_P (f1))
1899 x_sync (f1); 1946 x_sync (f1);
1900#endif 1947#endif
1948#endif
1949
1901 if (!FRAME_TOOLTIP_P (f1) 1950 if (!FRAME_TOOLTIP_P (f1)
1902 /* Tooltips and child frames count neither for 1951 /* Tooltips and child frames count neither for
1903 invisibility nor for deletions. */ 1952 invisibility nor for deletions. */
@@ -2214,17 +2263,24 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2214 /* Since a similar behavior was observed on the Lucid and Motif 2263 /* Since a similar behavior was observed on the Lucid and Motif
2215 builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now 2264 builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now
2216 don't delete the terminal for these builds either. */ 2265 don't delete the terminal for these builds either. */
2217 if (terminal->reference_count == 0 && 2266 if (terminal->reference_count == 0
2218 (terminal->type == output_x_window || terminal->type == output_pgtk)) 2267 && (terminal->type == output_x_window
2268 || terminal->type == output_pgtk))
2219 terminal->reference_count = 1; 2269 terminal->reference_count = 1;
2220#endif /* USE_X_TOOLKIT || USE_GTK */ 2270#endif /* USE_X_TOOLKIT || USE_GTK */
2271
2221 if (terminal->reference_count == 0) 2272 if (terminal->reference_count == 0)
2222 { 2273 {
2223 Lisp_Object tmp; 2274 Lisp_Object tmp;
2224 XSETTERMINAL (tmp, terminal); 2275 XSETTERMINAL (tmp, terminal);
2225 2276
2226 kb = NULL; 2277 kb = NULL;
2227 Fdelete_terminal (tmp, NILP (force) ? Qt : force); 2278
2279 /* If force is noelisp, the terminal is going away inside
2280 x_delete_terminal, and a recursive call to Fdelete_terminal
2281 is unsafe! */
2282 if (!EQ (force, Qnoelisp))
2283 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
2228 } 2284 }
2229 else 2285 else
2230 kb = terminal->kboard; 2286 kb = terminal->kboard;
diff --git a/src/frame.h b/src/frame.h
index d6fd62b2ac2..dcd32036b86 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1718,7 +1718,6 @@ extern void x_wm_set_icon_position (struct frame *, int, int);
1718#if !defined USE_X_TOOLKIT 1718#if !defined USE_X_TOOLKIT
1719extern const char *x_get_resource_string (const char *, const char *); 1719extern const char *x_get_resource_string (const char *, const char *);
1720#endif 1720#endif
1721extern void x_sync (struct frame *);
1722#endif /* HAVE_X_WINDOWS */ 1721#endif /* HAVE_X_WINDOWS */
1723 1722
1724#if !defined (HAVE_NS) && !defined (HAVE_PGTK) 1723#if !defined (HAVE_NS) && !defined (HAVE_PGTK)
diff --git a/src/gnutls.c b/src/gnutls.c
index 7f0aaf85a41..4093865cae5 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -2282,7 +2282,7 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
2282 Lisp_Object output; 2282 Lisp_Object output;
2283 if (GNUTLS_E_SUCCESS <= ret) 2283 if (GNUTLS_E_SUCCESS <= ret)
2284 output = make_unibyte_string (storage, storage_length); 2284 output = make_unibyte_string (storage, storage_length);
2285 explicit_bzero (storage, storage_length); 2285 memset_explicit (storage, 0, storage_length);
2286 gnutls_aead_cipher_deinit (acipher); 2286 gnutls_aead_cipher_deinit (acipher);
2287 2287
2288 if (ret < GNUTLS_E_SUCCESS) 2288 if (ret < GNUTLS_E_SUCCESS)
diff --git a/src/gtkutil.c b/src/gtkutil.c
index a6bba096a43..592bb497749 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -2103,7 +2103,7 @@ xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
2103 2103
2104 gdk_window_restack (gwin1, gwin2, above_flag); 2104 gdk_window_restack (gwin1, gwin2, above_flag);
2105#ifndef HAVE_PGTK 2105#ifndef HAVE_PGTK
2106 x_sync (f1); 2106 XSync (FRAME_X_DISPLAY (f1), False);
2107#else 2107#else
2108 gdk_flush (); 2108 gdk_flush ();
2109#endif 2109#endif
@@ -4793,7 +4793,7 @@ xg_update_scrollbar_pos (struct frame *f,
4793 here to get some events. */ 4793 here to get some events. */
4794 4794
4795#ifndef HAVE_PGTK 4795#ifndef HAVE_PGTK
4796 x_sync (f); 4796 XSync (FRAME_X_DISPLAY (f), False);
4797#else 4797#else
4798 gdk_flush (); 4798 gdk_flush ();
4799#endif 4799#endif
@@ -4894,7 +4894,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
4894 } 4894 }
4895 4895
4896#ifndef HAVE_PGTK 4896#ifndef HAVE_PGTK
4897 x_sync (f); 4897 XSync (FRAME_X_DISPLAY (f), False);
4898#else 4898#else
4899 gdk_flush (); 4899 gdk_flush ();
4900#endif 4900#endif
diff --git a/src/image.c b/src/image.c
index 600c32571e1..b881e43e951 100644
--- a/src/image.c
+++ b/src/image.c
@@ -193,8 +193,8 @@ static void anim_prune_animation_cache (Lisp_Object);
193#ifdef USE_CAIRO 193#ifdef USE_CAIRO
194 194
195static Emacs_Pix_Container 195static Emacs_Pix_Container
196image_create_pix_container (struct frame *f, unsigned int width, 196image_create_pix_container (unsigned int width, unsigned int height,
197 unsigned int height, unsigned int depth) 197 unsigned int depth)
198{ 198{
199 Emacs_Pix_Container pimg; 199 Emacs_Pix_Container pimg;
200 200
@@ -237,7 +237,7 @@ image_pix_container_create_from_bitmap_data (struct frame *f,
237 unsigned long fg, 237 unsigned long fg,
238 unsigned long bg) 238 unsigned long bg)
239{ 239{
240 Emacs_Pix_Container pimg = image_create_pix_container (f, width, height, 0); 240 Emacs_Pix_Container pimg = image_create_pix_container (width, height, 0);
241 int bytes_per_line = (width + (CHAR_BIT - 1)) / CHAR_BIT; 241 int bytes_per_line = (width + (CHAR_BIT - 1)) / CHAR_BIT;
242 242
243 for (int y = 0; y < height; y++) 243 for (int y = 0; y < height; y++)
@@ -3342,7 +3342,7 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d
3342 eassert (input_blocked_p ()); 3342 eassert (input_blocked_p ());
3343 3343
3344 /* Allocate a pixmap of the same size. */ 3344 /* Allocate a pixmap of the same size. */
3345 *pixmap = image_create_pix_container (f, width, height, depth); 3345 *pixmap = image_create_pix_container (width, height, depth);
3346 if (*pixmap == NO_PIXMAP) 3346 if (*pixmap == NO_PIXMAP)
3347 { 3347 {
3348 *pimg = NULL; 3348 *pimg = NULL;
@@ -11309,6 +11309,15 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
11309 img->face_font_size); 11309 img->face_font_size);
11310 viewbox_height = svg_css_length_to_pixels (iheight, dpi, 11310 viewbox_height = svg_css_length_to_pixels (iheight, dpi,
11311 img->face_font_size); 11311 img->face_font_size);
11312
11313 /* Here one dimension could be zero because in percent unit.
11314 So calculate this dimension with the other. */
11315 if (! (0 < viewbox_width) && (iwidth.unit == RSVG_UNIT_PERCENT))
11316 viewbox_width = (viewbox_height * viewbox.width / viewbox.height)
11317 * iwidth.length;
11318 else if (! (0 < viewbox_height) && (iheight.unit == RSVG_UNIT_PERCENT))
11319 viewbox_height = (viewbox_width * viewbox.height / viewbox.width)
11320 * iheight.length;
11312 } 11321 }
11313 else if (has_width && has_viewbox) 11322 else if (has_width && has_viewbox)
11314 { 11323 {
diff --git a/src/itree.c b/src/itree.c
index 04fa9e827a2..688d5c82476 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details. 15GNU General Public License for more details.
16 16
17You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20#include <config.h> 20#include <config.h>
21#include <math.h> 21#include <math.h>
@@ -1376,7 +1376,7 @@ itree_iterator_first_node (struct itree_tree *tree,
1376 return node; 1376 return node;
1377} 1377}
1378 1378
1379/* Start a iterator enumerating all intervals in [BEGIN,END) in the 1379/* Start an iterator enumerating all intervals in [BEGIN,END) in the
1380 given ORDER. */ 1380 given ORDER. */
1381 1381
1382struct itree_iterator * 1382struct itree_iterator *
diff --git a/src/itree.h b/src/itree.h
index 291fa53fd30..f1e2bf3bfde 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details. 15GNU General Public License for more details.
16 16
17You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20#ifndef ITREE_H 20#ifndef ITREE_H
21#define ITREE_H 21#define ITREE_H
@@ -25,6 +25,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25 25
26#include "lisp.h" 26#include "lisp.h"
27 27
28INLINE_HEADER_BEGIN
29
28/* The tree and node structs are mainly here, so they can be 30/* The tree and node structs are mainly here, so they can be
29 allocated. 31 allocated.
30 32
@@ -114,6 +116,11 @@ extern void itree_node_set_region (struct itree_tree *, struct itree_node *,
114 ptrdiff_t, ptrdiff_t); 116 ptrdiff_t, ptrdiff_t);
115extern struct itree_tree *itree_create (void); 117extern struct itree_tree *itree_create (void);
116extern void itree_destroy (struct itree_tree *); 118extern void itree_destroy (struct itree_tree *);
119INLINE bool
120itree_empty_p (struct itree_tree *tree)
121{
122 return !tree || !tree->root;
123}
117extern intmax_t itree_size (struct itree_tree *); 124extern intmax_t itree_size (struct itree_tree *);
118extern void itree_clear (struct itree_tree *); 125extern void itree_clear (struct itree_tree *);
119extern void itree_insert (struct itree_tree *, struct itree_node *, 126extern void itree_insert (struct itree_tree *, struct itree_node *,
@@ -178,4 +185,6 @@ struct itree_iterator
178#define ITREE_FOREACH_NARROW(beg, end) \ 185#define ITREE_FOREACH_NARROW(beg, end) \
179 itree_iterator_narrow (itree_iter_, beg, end) 186 itree_iterator_narrow (itree_iter_, beg, end)
180 187
188INLINE_HEADER_END
189
181#endif 190#endif
diff --git a/src/keyboard.c b/src/keyboard.c
index 811998823cc..d68b50428a9 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1910,10 +1910,14 @@ safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct window *w)
1910 1910
1911 specbind (Qinhibit_quit, Qt); 1911 specbind (Qinhibit_quit, Qt);
1912 1912
1913 if (current_buffer->long_line_optimizations_p) 1913 if (current_buffer->long_line_optimizations_p
1914 narrow_to_region_internal (make_fixnum (get_narrowed_begv (w, PT)), 1914 && long_line_locked_narrowing_region_size > 0)
1915 make_fixnum (get_narrowed_zv (w, PT)), 1915 {
1916 true); 1916 ptrdiff_t begv = get_locked_narrowing_begv (PT);
1917 ptrdiff_t zv = get_locked_narrowing_zv (PT);
1918 if (begv != BEG || zv != Z)
1919 narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv), hook);
1920 }
1917 1921
1918 run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), 1922 run_hook_with_args (2, ((Lisp_Object []) {hook, hook}),
1919 safe_run_hook_funcall); 1923 safe_run_hook_funcall);
@@ -12727,8 +12731,9 @@ the error might happen repeatedly and make Emacs nonfunctional.
12727 12731
12728Note that, when the current buffer contains one or more lines whose 12732Note that, when the current buffer contains one or more lines whose
12729length is above `long-line-threshold', these hook functions are called 12733length is above `long-line-threshold', these hook functions are called
12730with the buffer narrowed to a small portion around point, and the 12734with the buffer narrowed to a small portion around point (whose size
12731narrowing is locked (see `narrow-to-region'), so that these hook 12735is specified by `long-line-locked-narrowing-region-size'), and the
12736narrowing is locked (see `narrowing-lock'), so that these hook
12732functions cannot use `widen' to gain access to other portions of 12737functions cannot use `widen' to gain access to other portions of
12733buffer text. 12738buffer text.
12734 12739
@@ -12748,8 +12753,9 @@ avoid making Emacs unresponsive while the user types.
12748 12753
12749Note that, when the current buffer contains one or more lines whose 12754Note that, when the current buffer contains one or more lines whose
12750length is above `long-line-threshold', these hook functions are called 12755length is above `long-line-threshold', these hook functions are called
12751with the buffer narrowed to a small portion around point, and the 12756with the buffer narrowed to a small portion around point (whose size
12752narrowing is locked (see `narrow-to-region'), so that these hook 12757is specified by `long-line-locked-narrowing-region-size'), and the
12758narrowing is locked (see `narrowing-lock'), so that these hook
12753functions cannot use `widen' to gain access to other portions of 12759functions cannot use `widen' to gain access to other portions of
12754buffer text. 12760buffer text.
12755 12761
diff --git a/src/lisp.h b/src/lisp.h
index 3d9c48449aa..3791bf2b0c3 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4728,7 +4728,8 @@ extern void save_restriction_restore (Lisp_Object);
4728extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); 4728extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
4729extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, 4729extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
4730 ptrdiff_t, bool); 4730 ptrdiff_t, bool);
4731extern Lisp_Object narrow_to_region_internal (Lisp_Object, Lisp_Object, bool); 4731extern void narrow_to_region_locked (Lisp_Object, Lisp_Object, Lisp_Object);
4732extern void reset_outermost_narrowings (void);
4732extern void init_editfns (void); 4733extern void init_editfns (void);
4733extern void syms_of_editfns (void); 4734extern void syms_of_editfns (void);
4734 4735
@@ -5336,6 +5337,26 @@ __lsan_ignore_object (void const *p)
5336} 5337}
5337#endif 5338#endif
5338 5339
5340/* If built with USE_SANITIZER_UNALIGNED_LOAD defined, use compiler
5341 provided ASan functions to perform unaligned loads, allowing ASan
5342 to catch bugs which it might otherwise miss. */
5343#if defined HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H \
5344 && defined ADDRESS_SANITIZER \
5345 && defined USE_SANITIZER_UNALIGNED_LOAD
5346# include <sanitizer/common_interface_defs.h>
5347# if (SIZE_MAX == UINT64_MAX)
5348# define UNALIGNED_LOAD_SIZE(a, i) \
5349 (size_t) __sanitizer_unaligned_load64 ((void *) ((a) + (i)))
5350# elif (SIZE_MAX == UINT32_MAX)
5351# define UNALIGNED_LOAD_SIZE(a, i) \
5352 (size_t) __sanitizer_unaligned_load32 ((void *) ((a) + (i)))
5353# else
5354# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i))
5355# endif
5356#else
5357# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i))
5358#endif
5359
5339extern void xputenv (const char *); 5360extern void xputenv (const char *);
5340 5361
5341extern char *egetenv_internal (const char *, ptrdiff_t); 5362extern char *egetenv_internal (const char *, ptrdiff_t);
diff --git a/src/lread.c b/src/lread.c
index 0a6e4201e40..d838a18de5a 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -3375,7 +3375,7 @@ read_bool_vector (Lisp_Object readcharfun)
3375 break; 3375 break;
3376 } 3376 }
3377 if (INT_MULTIPLY_WRAPV (length, 10, &length) 3377 if (INT_MULTIPLY_WRAPV (length, 10, &length)
3378 | INT_ADD_WRAPV (length, c - '0', &length)) 3378 || INT_ADD_WRAPV (length, c - '0', &length))
3379 invalid_syntax ("#&", readcharfun); 3379 invalid_syntax ("#&", readcharfun);
3380 } 3380 }
3381 3381
@@ -3421,7 +3421,7 @@ skip_lazy_string (Lisp_Object readcharfun)
3421 break; 3421 break;
3422 } 3422 }
3423 if (INT_MULTIPLY_WRAPV (nskip, 10, &nskip) 3423 if (INT_MULTIPLY_WRAPV (nskip, 10, &nskip)
3424 | INT_ADD_WRAPV (nskip, c - '0', &nskip)) 3424 || INT_ADD_WRAPV (nskip, c - '0', &nskip))
3425 invalid_syntax ("#@", readcharfun); 3425 invalid_syntax ("#@", readcharfun);
3426 digits++; 3426 digits++;
3427 if (digits == 2 && nskip == 0) 3427 if (digits == 2 && nskip == 0)
@@ -5468,15 +5468,6 @@ to the specified file name if a suffix is allowed or required. */);
5468 Vload_suffixes = 5468 Vload_suffixes =
5469 Fcons (build_pure_c_string (MODULES_SECONDARY_SUFFIX), Vload_suffixes); 5469 Fcons (build_pure_c_string (MODULES_SECONDARY_SUFFIX), Vload_suffixes);
5470#endif 5470#endif
5471
5472 DEFVAR_LISP ("dynamic-library-suffixes", Vdynamic_library_suffixes,
5473 doc: /* A list of suffixes for loadable dynamic libraries. */);
5474 Vdynamic_library_suffixes =
5475 Fcons (build_pure_c_string (DYNAMIC_LIB_SECONDARY_SUFFIX), Qnil);
5476 Vdynamic_library_suffixes =
5477 Fcons (build_pure_c_string (DYNAMIC_LIB_SUFFIX),
5478 Vdynamic_library_suffixes);
5479
5480#endif 5471#endif
5481 DEFVAR_LISP ("module-file-suffix", Vmodule_file_suffix, 5472 DEFVAR_LISP ("module-file-suffix", Vmodule_file_suffix,
5482 doc: /* Suffix of loadable module file, or nil if modules are not supported. */); 5473 doc: /* Suffix of loadable module file, or nil if modules are not supported. */);
@@ -5485,6 +5476,20 @@ to the specified file name if a suffix is allowed or required. */);
5485#else 5476#else
5486 Vmodule_file_suffix = Qnil; 5477 Vmodule_file_suffix = Qnil;
5487#endif 5478#endif
5479
5480 DEFVAR_LISP ("dynamic-library-suffixes", Vdynamic_library_suffixes,
5481 doc: /* A list of suffixes for loadable dynamic libraries. */);
5482
5483#ifndef MSDOS
5484 Vdynamic_library_suffixes
5485 = Fcons (build_pure_c_string (DYNAMIC_LIB_SECONDARY_SUFFIX), Qnil);
5486 Vdynamic_library_suffixes
5487 = Fcons (build_pure_c_string (DYNAMIC_LIB_SUFFIX),
5488 Vdynamic_library_suffixes);
5489#else
5490 Vdynamic_library_suffixes = Qnil;
5491#endif
5492
5488 DEFVAR_LISP ("load-file-rep-suffixes", Vload_file_rep_suffixes, 5493 DEFVAR_LISP ("load-file-rep-suffixes", Vload_file_rep_suffixes,
5489 doc: /* List of suffixes that indicate representations of \ 5494 doc: /* List of suffixes that indicate representations of \
5490the same file. 5495the same file.
diff --git a/src/module-env-29.h b/src/module-env-29.h
index 6ca03773181..e69de29bb2d 100644
--- a/src/module-env-29.h
+++ b/src/module-env-29.h
@@ -1,3 +0,0 @@
1 /* Add module environment functions newly added in Emacs 29 here.
2 Before Emacs 29 is released, remove this comment and start
3 module-env-30.h on the master branch. */
diff --git a/src/module-env-30.h b/src/module-env-30.h
new file mode 100644
index 00000000000..6ca03773181
--- /dev/null
+++ b/src/module-env-30.h
@@ -0,0 +1,3 @@
1 /* Add module environment functions newly added in Emacs 29 here.
2 Before Emacs 29 is released, remove this comment and start
3 module-env-30.h on the master branch. */
diff --git a/src/pdumper.c b/src/pdumper.c
index 75fe697dcd7..70f90f0d8aa 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2748,7 +2748,7 @@ dump_hash_table (struct dump_context *ctx,
2748static dump_off 2748static dump_off
2749dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) 2749dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2750{ 2750{
2751#if CHECK_STRUCTS && !defined HASH_buffer_193CAA5E45 2751#if CHECK_STRUCTS && !defined HASH_buffer_DB34E5D09F
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;
@@ -2811,7 +2811,6 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2811 DUMP_FIELD_COPY (out, buffer, own_text.end_unchanged); 2811 DUMP_FIELD_COPY (out, buffer, own_text.end_unchanged);
2812 DUMP_FIELD_COPY (out, buffer, own_text.unchanged_modified); 2812 DUMP_FIELD_COPY (out, buffer, own_text.unchanged_modified);
2813 DUMP_FIELD_COPY (out, buffer, own_text.overlay_unchanged_modified); 2813 DUMP_FIELD_COPY (out, buffer, own_text.overlay_unchanged_modified);
2814 DUMP_FIELD_COPY (out, buffer, own_text.chars_unchanged_modified);
2815 if (buffer->own_text.intervals) 2814 if (buffer->own_text.intervals)
2816 dump_field_fixup_later (ctx, out, buffer, &buffer->own_text.intervals); 2815 dump_field_fixup_later (ctx, out, buffer, &buffer->own_text.intervals);
2817 dump_field_lv_rawptr (ctx, out, buffer, &buffer->own_text.markers, 2816 dump_field_lv_rawptr (ctx, out, buffer, &buffer->own_text.markers,
@@ -2863,7 +2862,7 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
2863 DUMP_FIELD_COPY (out, buffer, inhibit_buffer_hooks); 2862 DUMP_FIELD_COPY (out, buffer, inhibit_buffer_hooks);
2864 DUMP_FIELD_COPY (out, buffer, long_line_optimizations_p); 2863 DUMP_FIELD_COPY (out, buffer, long_line_optimizations_p);
2865 2864
2866 if (buffer->overlays && buffer->overlays->root != NULL) 2865 if (!itree_empty_p (buffer->overlays))
2867 /* We haven't implemented the code to dump overlays. */ 2866 /* We haven't implemented the code to dump overlays. */
2868 emacs_abort (); 2867 emacs_abort ();
2869 else 2868 else
@@ -3003,7 +3002,7 @@ dump_vectorlike (struct dump_context *ctx,
3003 Lisp_Object lv, 3002 Lisp_Object lv,
3004 dump_off offset) 3003 dump_off offset)
3005{ 3004{
3006#if CHECK_STRUCTS && !defined HASH_pvec_type_AFF6FED5BD 3005#if CHECK_STRUCTS && !defined HASH_pvec_type_5F2059C47E
3007# error "pvec_type changed. See CHECK_STRUCTS comment in config.h." 3006# error "pvec_type changed. See CHECK_STRUCTS comment in config.h."
3008#endif 3007#endif
3009 const struct Lisp_Vector *v = XVECTOR (lv); 3008 const struct Lisp_Vector *v = XVECTOR (lv);
diff --git a/src/sqlite.c b/src/sqlite.c
index ac860f55bcd..d9b9333fb3c 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -55,6 +55,7 @@ DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*));
55#if SQLITE_VERSION_NUMBER >= 3007015 55#if SQLITE_VERSION_NUMBER >= 3007015
56DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); 56DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int));
57#endif 57#endif
58DEF_DLL_FN (SQLITE_API const char*, sqlite3_libversion, (void));
58DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); 59DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*));
59DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); 60DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*));
60DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); 61DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*));
@@ -96,6 +97,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension,
96# if SQLITE_VERSION_NUMBER >= 3007015 97# if SQLITE_VERSION_NUMBER >= 3007015
97# undef sqlite3_errstr 98# undef sqlite3_errstr
98# endif 99# endif
100# undef sqlite3_libversion
99# undef sqlite3_step 101# undef sqlite3_step
100# undef sqlite3_changes 102# undef sqlite3_changes
101# undef sqlite3_column_count 103# undef sqlite3_column_count
@@ -124,6 +126,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension,
124# if SQLITE_VERSION_NUMBER >= 3007015 126# if SQLITE_VERSION_NUMBER >= 3007015
125# define sqlite3_errstr fn_sqlite3_errstr 127# define sqlite3_errstr fn_sqlite3_errstr
126# endif 128# endif
129# define sqlite3_libversion fn_sqlite3_libversion
127# define sqlite3_step fn_sqlite3_step 130# define sqlite3_step fn_sqlite3_step
128# define sqlite3_changes fn_sqlite3_changes 131# define sqlite3_changes fn_sqlite3_changes
129# define sqlite3_column_count fn_sqlite3_column_count 132# define sqlite3_column_count fn_sqlite3_column_count
@@ -155,6 +158,7 @@ load_dll_functions (HMODULE library)
155#if SQLITE_VERSION_NUMBER >= 3007015 158#if SQLITE_VERSION_NUMBER >= 3007015
156 LOAD_DLL_FN (library, sqlite3_errstr); 159 LOAD_DLL_FN (library, sqlite3_errstr);
157#endif 160#endif
161 LOAD_DLL_FN (library, sqlite3_libversion);
158 LOAD_DLL_FN (library, sqlite3_step); 162 LOAD_DLL_FN (library, sqlite3_step);
159 LOAD_DLL_FN (library, sqlite3_changes); 163 LOAD_DLL_FN (library, sqlite3_changes);
160 LOAD_DLL_FN (library, sqlite3_column_count); 164 LOAD_DLL_FN (library, sqlite3_column_count);
@@ -763,6 +767,16 @@ This will free the resources held by SET. */)
763 return Qt; 767 return Qt;
764} 768}
765 769
770DEFUN ("sqlite-version", Fsqlite_version, Ssqlite_version, 0, 0, 0,
771 doc: /* Return the version string of the SQLite library.
772Signal an error if SQLite support is not available. */)
773 (void)
774{
775 if (!init_sqlite_functions ())
776 error ("sqlite support is not available");
777 return build_string (sqlite3_libversion ());
778}
779
766#endif /* HAVE_SQLITE3 */ 780#endif /* HAVE_SQLITE3 */
767 781
768DEFUN ("sqlitep", Fsqlitep, Ssqlitep, 1, 1, 0, 782DEFUN ("sqlitep", Fsqlitep, Ssqlitep, 1, 1, 0,
@@ -814,6 +828,7 @@ syms_of_sqlite (void)
814 defsubr (&Ssqlite_columns); 828 defsubr (&Ssqlite_columns);
815 defsubr (&Ssqlite_more_p); 829 defsubr (&Ssqlite_more_p);
816 defsubr (&Ssqlite_finalize); 830 defsubr (&Ssqlite_finalize);
831 defsubr (&Ssqlite_version);
817 DEFSYM (Qset, "set"); 832 DEFSYM (Qset, "set");
818 DEFSYM (Qfull, "full"); 833 DEFSYM (Qfull, "full");
819#endif 834#endif
diff --git a/src/sysdep.c b/src/sysdep.c
index 736723bdf3d..8402ffe308c 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2653,10 +2653,11 @@ emacs_perror (char const *message)
2653int 2653int
2654renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst) 2654renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst)
2655{ 2655{
2656#if defined SYS_renameat2 && defined RENAME_NOREPLACE 2656#if HAVE_RENAMEAT2 && defined RENAME_NOREPLACE
2657 return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE);
2658#elif defined CYGWIN && defined RENAME_NOREPLACE
2659 return renameat2 (srcfd, src, dstfd, dst, RENAME_NOREPLACE); 2657 return renameat2 (srcfd, src, dstfd, dst, RENAME_NOREPLACE);
2658#elif defined SYS_renameat2 && defined RENAME_NOREPLACE
2659 /* Linux kernel 3.15 (2014) or later, with glibc 2.27 (2018) or earlier. */
2660 return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE);
2660#elif defined RENAME_EXCL 2661#elif defined RENAME_EXCL
2661 return renameatx_np (srcfd, src, dstfd, dst, RENAME_EXCL); 2662 return renameatx_np (srcfd, src, dstfd, dst, RENAME_EXCL);
2662#else 2663#else
diff --git a/src/timefns.c b/src/timefns.c
index eed2edf1cc0..dcc6403fd9d 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -40,6 +40,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
40#include <stdio.h> 40#include <stdio.h>
41#include <stdlib.h> 41#include <stdlib.h>
42 42
43#ifdef WINDOWSNT
44extern clock_t sys_clock (void);
45#endif
46
43#ifdef HAVE_TIMEZONE_T 47#ifdef HAVE_TIMEZONE_T
44# include <sys/param.h> 48# include <sys/param.h>
45# if defined __NetBSD_Version__ && __NetBSD_Version__ < 700000000 49# if defined __NetBSD_Version__ && __NetBSD_Version__ < 700000000
@@ -1194,7 +1198,7 @@ For example, nil stands for the current time. */)
1194 quicker while we're at it. This means (time-subtract X X) does 1198 quicker while we're at it. This means (time-subtract X X) does
1195 not signal an error if X is not a valid time value, but that's OK. */ 1199 not signal an error if X is not a valid time value, but that's OK. */
1196 if (BASE_EQ (a, b)) 1200 if (BASE_EQ (a, b))
1197 return timespec_to_lisp ((struct timespec) {0}); 1201 return make_lisp_time ((struct timespec) {0});
1198 1202
1199 return time_arith (a, b, true); 1203 return time_arith (a, b, true);
1200} 1204}
diff --git a/src/treesit.c b/src/treesit.c
index 21e1f866f78..c882d455137 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -52,7 +52,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
52#undef ts_node_named_descendant_for_byte_range 52#undef ts_node_named_descendant_for_byte_range
53#undef ts_node_next_named_sibling 53#undef ts_node_next_named_sibling
54#undef ts_node_next_sibling 54#undef ts_node_next_sibling
55#undef ts_node_parent
56#undef ts_node_prev_named_sibling 55#undef ts_node_prev_named_sibling
57#undef ts_node_prev_sibling 56#undef ts_node_prev_sibling
58#undef ts_node_start_byte 57#undef ts_node_start_byte
@@ -76,7 +75,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
76#undef ts_query_predicates_for_pattern 75#undef ts_query_predicates_for_pattern
77#undef ts_query_string_value_for_id 76#undef ts_query_string_value_for_id
78#undef ts_set_allocator 77#undef ts_set_allocator
78#undef ts_tree_cursor_copy
79#undef ts_tree_cursor_current_node 79#undef ts_tree_cursor_current_node
80#undef ts_tree_cursor_delete
80#undef ts_tree_cursor_goto_first_child 81#undef ts_tree_cursor_goto_first_child
81#undef ts_tree_cursor_goto_next_sibling 82#undef ts_tree_cursor_goto_next_sibling
82#undef ts_tree_cursor_goto_parent 83#undef ts_tree_cursor_goto_parent
@@ -109,7 +110,6 @@ DEF_DLL_FN (TSNode, ts_node_named_descendant_for_byte_range,
109 (TSNode, uint32_t, uint32_t)); 110 (TSNode, uint32_t, uint32_t));
110DEF_DLL_FN (TSNode, ts_node_next_named_sibling, (TSNode)); 111DEF_DLL_FN (TSNode, ts_node_next_named_sibling, (TSNode));
111DEF_DLL_FN (TSNode, ts_node_next_sibling, (TSNode)); 112DEF_DLL_FN (TSNode, ts_node_next_sibling, (TSNode));
112DEF_DLL_FN (TSNode, ts_node_parent, (TSNode));
113DEF_DLL_FN (TSNode, ts_node_prev_named_sibling, (TSNode)); 113DEF_DLL_FN (TSNode, ts_node_prev_named_sibling, (TSNode));
114DEF_DLL_FN (TSNode, ts_node_prev_sibling, (TSNode)); 114DEF_DLL_FN (TSNode, ts_node_prev_sibling, (TSNode));
115DEF_DLL_FN (uint32_t, ts_node_start_byte, (TSNode)); 115DEF_DLL_FN (uint32_t, ts_node_start_byte, (TSNode));
@@ -143,7 +143,9 @@ DEF_DLL_FN (const char *, ts_query_string_value_for_id,
143 (const TSQuery *, uint32_t, uint32_t *)); 143 (const TSQuery *, uint32_t, uint32_t *));
144DEF_DLL_FN (void, ts_set_allocator, 144DEF_DLL_FN (void, ts_set_allocator,
145 (void *(*)(size_t), void *(*)(size_t, size_t), void *(*)(void *, size_t), void (*)(void *))); 145 (void *(*)(size_t), void *(*)(size_t, size_t), void *(*)(void *, size_t), void (*)(void *)));
146DEF_DLL_FN (TSTreeCursor, ts_tree_cursor_copy, (const TSTreeCursor *));
146DEF_DLL_FN (TSNode, ts_tree_cursor_current_node, (const TSTreeCursor *)); 147DEF_DLL_FN (TSNode, ts_tree_cursor_current_node, (const TSTreeCursor *));
148DEF_DLL_FN (void, ts_tree_cursor_delete, (const TSTreeCursor *));
147DEF_DLL_FN (bool, ts_tree_cursor_goto_first_child, (TSTreeCursor *)); 149DEF_DLL_FN (bool, ts_tree_cursor_goto_first_child, (TSTreeCursor *));
148DEF_DLL_FN (bool, ts_tree_cursor_goto_next_sibling, (TSTreeCursor *)); 150DEF_DLL_FN (bool, ts_tree_cursor_goto_next_sibling, (TSTreeCursor *));
149DEF_DLL_FN (bool, ts_tree_cursor_goto_parent, (TSTreeCursor *)); 151DEF_DLL_FN (bool, ts_tree_cursor_goto_parent, (TSTreeCursor *));
@@ -182,7 +184,6 @@ init_treesit_functions (void)
182 LOAD_DLL_FN (library, ts_node_named_descendant_for_byte_range); 184 LOAD_DLL_FN (library, ts_node_named_descendant_for_byte_range);
183 LOAD_DLL_FN (library, ts_node_next_named_sibling); 185 LOAD_DLL_FN (library, ts_node_next_named_sibling);
184 LOAD_DLL_FN (library, ts_node_next_sibling); 186 LOAD_DLL_FN (library, ts_node_next_sibling);
185 LOAD_DLL_FN (library, ts_node_parent);
186 LOAD_DLL_FN (library, ts_node_prev_named_sibling); 187 LOAD_DLL_FN (library, ts_node_prev_named_sibling);
187 LOAD_DLL_FN (library, ts_node_prev_sibling); 188 LOAD_DLL_FN (library, ts_node_prev_sibling);
188 LOAD_DLL_FN (library, ts_node_start_byte); 189 LOAD_DLL_FN (library, ts_node_start_byte);
@@ -206,7 +207,9 @@ init_treesit_functions (void)
206 LOAD_DLL_FN (library, ts_query_predicates_for_pattern); 207 LOAD_DLL_FN (library, ts_query_predicates_for_pattern);
207 LOAD_DLL_FN (library, ts_query_string_value_for_id); 208 LOAD_DLL_FN (library, ts_query_string_value_for_id);
208 LOAD_DLL_FN (library, ts_set_allocator); 209 LOAD_DLL_FN (library, ts_set_allocator);
210 LOAD_DLL_FN (library, ts_tree_cursor_copy);
209 LOAD_DLL_FN (library, ts_tree_cursor_current_node); 211 LOAD_DLL_FN (library, ts_tree_cursor_current_node);
212 LOAD_DLL_FN (library, ts_tree_cursor_delete);
210 LOAD_DLL_FN (library, ts_tree_cursor_goto_first_child); 213 LOAD_DLL_FN (library, ts_tree_cursor_goto_first_child);
211 LOAD_DLL_FN (library, ts_tree_cursor_goto_next_sibling); 214 LOAD_DLL_FN (library, ts_tree_cursor_goto_next_sibling);
212 LOAD_DLL_FN (library, ts_tree_cursor_goto_parent); 215 LOAD_DLL_FN (library, ts_tree_cursor_goto_parent);
@@ -239,7 +242,6 @@ init_treesit_functions (void)
239#define ts_node_named_descendant_for_byte_range fn_ts_node_named_descendant_for_byte_range 242#define ts_node_named_descendant_for_byte_range fn_ts_node_named_descendant_for_byte_range
240#define ts_node_next_named_sibling fn_ts_node_next_named_sibling 243#define ts_node_next_named_sibling fn_ts_node_next_named_sibling
241#define ts_node_next_sibling fn_ts_node_next_sibling 244#define ts_node_next_sibling fn_ts_node_next_sibling
242#define ts_node_parent fn_ts_node_parent
243#define ts_node_prev_named_sibling fn_ts_node_prev_named_sibling 245#define ts_node_prev_named_sibling fn_ts_node_prev_named_sibling
244#define ts_node_prev_sibling fn_ts_node_prev_sibling 246#define ts_node_prev_sibling fn_ts_node_prev_sibling
245#define ts_node_start_byte fn_ts_node_start_byte 247#define ts_node_start_byte fn_ts_node_start_byte
@@ -263,7 +265,9 @@ init_treesit_functions (void)
263#define ts_query_predicates_for_pattern fn_ts_query_predicates_for_pattern 265#define ts_query_predicates_for_pattern fn_ts_query_predicates_for_pattern
264#define ts_query_string_value_for_id fn_ts_query_string_value_for_id 266#define ts_query_string_value_for_id fn_ts_query_string_value_for_id
265#define ts_set_allocator fn_ts_set_allocator 267#define ts_set_allocator fn_ts_set_allocator
268#define ts_tree_cursor_copy fn_ts_tree_cursor_copy
266#define ts_tree_cursor_current_node fn_ts_tree_cursor_current_node 269#define ts_tree_cursor_current_node fn_ts_tree_cursor_current_node
270#define ts_tree_cursor_delete fn_ts_tree_cursor_delete
267#define ts_tree_cursor_goto_first_child fn_ts_tree_cursor_goto_first_child 271#define ts_tree_cursor_goto_first_child fn_ts_tree_cursor_goto_first_child
268#define ts_tree_cursor_goto_next_sibling fn_ts_tree_cursor_goto_next_sibling 272#define ts_tree_cursor_goto_next_sibling fn_ts_tree_cursor_goto_next_sibling
269#define ts_tree_cursor_goto_parent fn_ts_tree_cursor_goto_parent 273#define ts_tree_cursor_goto_parent fn_ts_tree_cursor_goto_parent
@@ -288,7 +292,7 @@ init_treesit_functions (void)
288 slow enough to make insignificant any performance advantages from 292 slow enough to make insignificant any performance advantages from
289 using the cursor. Not exposing the cursor also minimizes the 293 using the cursor. Not exposing the cursor also minimizes the
290 number of new types this adds to Emacs Lisp; currently, this adds 294 number of new types this adds to Emacs Lisp; currently, this adds
291 only the parser and node types. 295 only the parser, node, and compiled query types.
292 296
293 - Because updating the change is handled on the C level as each 297 - Because updating the change is handled on the C level as each
294 change is made in the buffer, there is no way for Lisp to update 298 change is made in the buffer, there is no way for Lisp to update
@@ -314,7 +318,7 @@ init_treesit_functions (void)
314 See: https://github.com/tree-sitter/tree-sitter/issues/445 318 See: https://github.com/tree-sitter/tree-sitter/issues/445
315 319
316 treesit.h has some commentary on the two main data structure for 320 treesit.h has some commentary on the two main data structure for
317 the parser and node. treesit_ensure_position_synced has some 321 the parser and node. treesit_sync_visible_region has some
318 commentary on how we make tree-sitter play well with narrowing (the 322 commentary on how we make tree-sitter play well with narrowing (the
319 tree-sitter parser only sees the visible region, so we need to 323 tree-sitter parser only sees the visible region, so we need to
320 translate positions back and forth). Most action happens in 324 translate positions back and forth). Most action happens in
@@ -384,7 +388,18 @@ init_treesit_functions (void)
384 mysteriously drops. 3) what if a user uses so many stuff that the 388 mysteriously drops. 3) what if a user uses so many stuff that the
385 default cache size (20) is not enough and we end up thrashing? 389 default cache size (20) is not enough and we end up thrashing?
386 These are all imaginary scenarios but they are not impossible 390 These are all imaginary scenarios but they are not impossible
387 :-) */ 391 :-)
392
393 Parsers in indirect buffers: We make indirect buffers to share the
394 parser of its base buffer. Indirect buffers and their base buffer
395 share the same buffer content but not other buffer attributes. If
396 they have separate parser lists, changes made in an indirect buffer
397 will only update parsers of that indirect buffer, and not parsers
398 in the base buffer or other indirect buffers, and vice versa. We
399 could keep track of all the base and indirect buffers, and update
400 all of their parsers, but ultimately decide to take a simpler
401 approach, which is to make indirect buffers share their base
402 buffer's parser list. The discussion can be found in bug#59693. */
388 403
389 404
390/*** Initialization */ 405/*** Initialization */
@@ -697,9 +712,10 @@ void
697treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, 712treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
698 ptrdiff_t new_end_byte) 713 ptrdiff_t new_end_byte)
699{ 714{
700 Lisp_Object parser_list; 715 struct buffer *base_buffer = current_buffer;
701 716 if (current_buffer->base_buffer)
702 parser_list = BVAR (current_buffer, ts_parser_list); 717 base_buffer = current_buffer->base_buffer;
718 Lisp_Object parser_list = BVAR (base_buffer, ts_parser_list);
703 719
704 FOR_EACH_TAIL_SAFE (parser_list) 720 FOR_EACH_TAIL_SAFE (parser_list)
705 { 721 {
@@ -707,6 +723,8 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
707 Lisp_Object lisp_parser = XCAR (parser_list); 723 Lisp_Object lisp_parser = XCAR (parser_list);
708 treesit_check_parser (lisp_parser); 724 treesit_check_parser (lisp_parser);
709 TSTree *tree = XTS_PARSER (lisp_parser)->tree; 725 TSTree *tree = XTS_PARSER (lisp_parser)->tree;
726 /* See comment (ref:visible-beg-null) if you wonder why we don't
727 update visible_beg/end when tree is NULL. */
710 if (tree != NULL) 728 if (tree != NULL)
711 { 729 {
712 eassert (start_byte <= old_end_byte); 730 eassert (start_byte <= old_end_byte);
@@ -742,7 +760,7 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
742 XTS_PARSER (lisp_parser)->timestamp++; 760 XTS_PARSER (lisp_parser)->timestamp++;
743 761
744 /* VISIBLE_BEG/END records tree-sitter's range of view in 762 /* VISIBLE_BEG/END records tree-sitter's range of view in
745 the buffer. Ee need to adjust them when tree-sitter's 763 the buffer. We need to adjust them when tree-sitter's
746 view changes. */ 764 view changes. */
747 ptrdiff_t visi_beg_delta; 765 ptrdiff_t visi_beg_delta;
748 if (old_end_byte > new_end_byte) 766 if (old_end_byte > new_end_byte)
@@ -765,20 +783,68 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
765 } 783 }
766} 784}
767 785
768/* Make sure PARSER's visible_beg and visible_end are in sync with 786/* Comment (ref:visible-beg-null) The purpose of visible_beg/end is to
769 BUF_BEGV_BYTE and BUG_ZV_BYTE. When calling this function you must 787 keep track of "which part of the buffer does the tree-sitter tree
770 make sure the current buffer's size is not larger than UINT32_MAX. 788 see", in order to update the tree correctly. Visible_beg/end have
771 Basically always call treesit_check_buffer_size before this 789 two purposes: they "clip" buffer changes within them, and they
772 function. */ 790 translate positions in the buffer to positions in the tree
791 (buffer position - visible_beg = tree position).
792
793 Conceptually, visible_beg/end hold the visible region of the buffer
794 when we last reparsed. In-between two reparses, we don't really
795 care if the visible region of the buffer changes.
796
797 Right before we reparse, we make tree-sitter's visible region
798 match that of the buffer, and update visible_beg/end.
799
800 That is, the whole purpose of visible_beg/end (and also of
801 treesit_record_change and treesit_sync_visible_region) is to update
802 the tree (by ts_tree_edit). So if the tree is NULL,
803 visible_beg/end are considered uninitialized. Only when we already
804 have a tree, do we need to keep track of position changes and
805 update it correctly, so it can be fed into ts_parser_parse as the
806 old tree, so that tree-sitter will only parse the changed part,
807 incrementally.
808
809 In a nutshell, tree-sitter incremental parsing in Emacs looks like:
810
811 treesit_record_change (tree) \
812 treesit_record_change (tree) | user edits buffer
813 ... /
814
815 treesit_sync_visible_region (tree) \ treesit_ensure_parsed
816 ts_parser_parse(tree) -> tree /
817
818 treesit_record_change (tree) \
819 treesit_record_change (tree) | user edits buffer
820 ... /
821
822 and so on. */
823
824/* Make sure the tree's visible range is in sync with the buffer's
825 visible range, and PARSER's visible_beg and visible_end are in sync
826 with BUF_BEGV_BYTE and BUG_ZV_BYTE. When calling this function you
827 must make sure the current buffer's size in bytes is not larger than
828 UINT32_MAX. Basically, always call treesit_check_buffer_size before
829 this function.
830
831 If buffer range changed since last parse (visible_beg/end doesn't
832 match buffer visible beginning/end), set need_reparse to true. */
773static void 833static void
774treesit_ensure_position_synced (Lisp_Object parser) 834treesit_sync_visible_region (Lisp_Object parser)
775{ 835{
776 TSTree *tree = XTS_PARSER (parser)->tree; 836 TSTree *tree = XTS_PARSER (parser)->tree;
837 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
777 838
839 /* If we are setting visible_beg/end for the first time, we can skip
840 the offset acrobatics and updating the tree below. */
778 if (tree == NULL) 841 if (tree == NULL)
779 return; 842 {
843 XTS_PARSER (parser)->visible_beg = BUF_BEGV_BYTE (buffer);
844 XTS_PARSER (parser)->visible_end = BUF_ZV_BYTE (buffer);
845 return;
846 }
780 847
781 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
782 ptrdiff_t visible_beg = XTS_PARSER (parser)->visible_beg; 848 ptrdiff_t visible_beg = XTS_PARSER (parser)->visible_beg;
783 ptrdiff_t visible_end = XTS_PARSER (parser)->visible_end; 849 ptrdiff_t visible_end = XTS_PARSER (parser)->visible_end;
784 eassert (0 <= visible_beg); 850 eassert (0 <= visible_beg);
@@ -787,6 +853,12 @@ treesit_ensure_position_synced (Lisp_Object parser)
787 eassert (BUF_BEGV_BYTE (buffer) <= UINT32_MAX); 853 eassert (BUF_BEGV_BYTE (buffer) <= UINT32_MAX);
788 eassert (BUF_ZV_BYTE (buffer) <= UINT32_MAX); 854 eassert (BUF_ZV_BYTE (buffer) <= UINT32_MAX);
789 855
856 /* If buffer restriction changed and user requests for a node (hence
857 this function is called), we need to reparse. */
858 if (visible_beg != BUF_BEGV_BYTE (buffer)
859 || visible_end != BUF_ZV_BYTE (buffer))
860 XTS_PARSER (parser)->need_reparse = true;
861
790 /* Before we parse or set ranges, catch up with the narrowing 862 /* Before we parse or set ranges, catch up with the narrowing
791 situation. We change visible_beg and visible_end to match 863 situation. We change visible_beg and visible_end to match
792 BUF_BEGV_BYTE and BUF_ZV_BYTE, and inform tree-sitter of the 864 BUF_BEGV_BYTE and BUF_ZV_BYTE, and inform tree-sitter of the
@@ -832,6 +904,8 @@ treesit_ensure_position_synced (Lisp_Object parser)
832 } 904 }
833 eassert (0 <= visible_beg); 905 eassert (0 <= visible_beg);
834 eassert (visible_beg <= visible_end); 906 eassert (visible_beg <= visible_end);
907 eassert (visible_beg == BUF_BEGV_BYTE (buffer));
908 eassert (visible_end == BUF_ZV_BYTE (buffer));
835 909
836 XTS_PARSER (parser)->visible_beg = visible_beg; 910 XTS_PARSER (parser)->visible_beg = visible_beg;
837 XTS_PARSER (parser)->visible_end = visible_end; 911 XTS_PARSER (parser)->visible_end = visible_end;
@@ -875,16 +949,19 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree,
875static void 949static void
876treesit_ensure_parsed (Lisp_Object parser) 950treesit_ensure_parsed (Lisp_Object parser)
877{ 951{
952 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
953
954 /* Before we parse, catch up with the narrowing situation. */
955 treesit_check_buffer_size (buffer);
956 /* This function has to run before we check for need_reparse flag,
957 because it might set the flag to true. */
958 treesit_sync_visible_region (parser);
959
878 if (!XTS_PARSER (parser)->need_reparse) 960 if (!XTS_PARSER (parser)->need_reparse)
879 return; 961 return;
880 TSParser *treesit_parser = XTS_PARSER (parser)->parser; 962 TSParser *treesit_parser = XTS_PARSER (parser)->parser;
881 TSTree *tree = XTS_PARSER (parser)->tree; 963 TSTree *tree = XTS_PARSER (parser)->tree;
882 TSInput input = XTS_PARSER (parser)->input; 964 TSInput input = XTS_PARSER (parser)->input;
883 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
884
885 /* Before we parse, catch up with the narrowing situation. */
886 treesit_check_buffer_size (buffer);
887 treesit_ensure_position_synced (parser);
888 965
889 TSTree *new_tree = ts_parser_parse (treesit_parser, tree, input); 966 TSTree *new_tree = ts_parser_parse (treesit_parser, tree, input);
890 /* This should be very rare (impossible, really): it only happens 967 /* This should be very rare (impossible, really): it only happens
@@ -983,8 +1060,8 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser,
983 TSInput input = {lisp_parser, treesit_read_buffer, TSInputEncodingUTF8}; 1060 TSInput input = {lisp_parser, treesit_read_buffer, TSInputEncodingUTF8};
984 lisp_parser->input = input; 1061 lisp_parser->input = input;
985 lisp_parser->need_reparse = true; 1062 lisp_parser->need_reparse = true;
986 lisp_parser->visible_beg = BUF_BEGV (XBUFFER (buffer)); 1063 lisp_parser->visible_beg = BUF_BEGV_BYTE (XBUFFER (buffer));
987 lisp_parser->visible_end = BUF_ZV (XBUFFER (buffer)); 1064 lisp_parser->visible_end = BUF_ZV_BYTE (XBUFFER (buffer));
988 lisp_parser->timestamp = 0; 1065 lisp_parser->timestamp = 0;
989 lisp_parser->deleted = false; 1066 lisp_parser->deleted = false;
990 lisp_parser->has_range = false; 1067 lisp_parser->has_range = false;
@@ -1191,12 +1268,16 @@ DEFUN ("treesit-parser-create",
1191 1, 3, 0, 1268 1, 3, 0,
1192 doc: /* Create and return a parser in BUFFER for LANGUAGE. 1269 doc: /* Create and return a parser in BUFFER for LANGUAGE.
1193 1270
1194The parser is automatically added to BUFFER's parser list, as 1271The parser is automatically added to BUFFER's parser list, as returned
1195returned by `treesit-parser-list'. 1272by `treesit-parser-list'. LANGUAGE is a language symbol. If BUFFER
1196LANGUAGE is a language symbol. If BUFFER is nil or omitted, it 1273is nil or omitted, it defaults to the current buffer. If BUFFER
1197defaults to the current buffer. If BUFFER already has a parser for 1274already has a parser for LANGUAGE, return that parser, but if NO-REUSE
1198LANGUAGE, return that parser, but if NO-REUSE is non-nil, always 1275is non-nil, always create a new parser.
1199create a new parser. */) 1276
1277If that buffer is an indirect buffer, its base buffer is used instead.
1278That is, indirect buffers use their base buffer's parsers. Lisp
1279programs should widen as necessary should they want to use a parser in
1280an indirect buffer. */)
1200 (Lisp_Object language, Lisp_Object buffer, Lisp_Object no_reuse) 1281 (Lisp_Object language, Lisp_Object buffer, Lisp_Object no_reuse)
1201{ 1282{
1202 treesit_initialize (); 1283 treesit_initialize ();
@@ -1210,16 +1291,21 @@ create a new parser. */)
1210 CHECK_BUFFER (buffer); 1291 CHECK_BUFFER (buffer);
1211 buf = XBUFFER (buffer); 1292 buf = XBUFFER (buffer);
1212 } 1293 }
1294 if (buf->base_buffer)
1295 buf = buf->base_buffer;
1296
1213 treesit_check_buffer_size (buf); 1297 treesit_check_buffer_size (buf);
1214 1298
1215 /* See if we can reuse a parser. */ 1299 /* See if we can reuse a parser. */
1216 for (Lisp_Object tail = BVAR (buf, ts_parser_list); 1300 if (NILP (no_reuse))
1217 NILP (no_reuse) && !NILP (tail);
1218 tail = XCDR (tail))
1219 { 1301 {
1220 struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail)); 1302 Lisp_Object tail = BVAR (buf, ts_parser_list);
1221 if (EQ (parser->language_symbol, language)) 1303 FOR_EACH_TAIL (tail)
1222 return XCAR (tail); 1304 {
1305 struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail));
1306 if (EQ (parser->language_symbol, language))
1307 return XCAR (tail);
1308 }
1223 } 1309 }
1224 1310
1225 /* Load language. */ 1311 /* Load language. */
@@ -1268,7 +1354,10 @@ DEFUN ("treesit-parser-list",
1268 Ftreesit_parser_list, Streesit_parser_list, 1354 Ftreesit_parser_list, Streesit_parser_list,
1269 0, 1, 0, 1355 0, 1, 0,
1270 doc: /* Return BUFFER's parser list. 1356 doc: /* Return BUFFER's parser list.
1271BUFFER defaults to the current buffer. */) 1357
1358BUFFER defaults to the current buffer. If that buffer is an indirect
1359buffer, its base buffer is used instead. That is, indirect buffers
1360use their base buffer's parsers. */)
1272 (Lisp_Object buffer) 1361 (Lisp_Object buffer)
1273{ 1362{
1274 struct buffer *buf; 1363 struct buffer *buf;
@@ -1279,6 +1368,9 @@ BUFFER defaults to the current buffer. */)
1279 CHECK_BUFFER (buffer); 1368 CHECK_BUFFER (buffer);
1280 buf = XBUFFER (buffer); 1369 buf = XBUFFER (buffer);
1281 } 1370 }
1371 if (buf->base_buffer)
1372 buf = buf->base_buffer;
1373
1282 /* Return a fresh list so messing with that list doesn't affect our 1374 /* Return a fresh list so messing with that list doesn't affect our
1283 internal data. */ 1375 internal data. */
1284 Lisp_Object return_list = Qnil; 1376 Lisp_Object return_list = Qnil;
@@ -1365,9 +1457,10 @@ treesit_check_range_argument (Lisp_Object ranges)
1365 CHECK_LIST_END (tail, ranges); 1457 CHECK_LIST_END (tail, ranges);
1366} 1458}
1367 1459
1368/* Generate a list of ranges in Lisp from RANGES. This function 1460/* Generate a list of ranges in Lisp from RANGES. Assumes tree-sitter
1369 doesn't take ownership of RANGES. BUFFER is used to convert 1461 tree and the buffer has the same visible region (wrt narrowing).
1370 between tree-sitter buffer offset and buffer position. */ 1462 This function doesn't take ownership of RANGES. BUFFER is used to
1463 convert between tree-sitter buffer offset and buffer position. */
1371static Lisp_Object 1464static Lisp_Object
1372treesit_make_ranges (const TSRange *ranges, uint32_t len, 1465treesit_make_ranges (const TSRange *ranges, uint32_t len,
1373 struct buffer *buffer) 1466 struct buffer *buffer)
@@ -1412,7 +1505,7 @@ buffer. */)
1412 treesit_initialize (); 1505 treesit_initialize ();
1413 /* Before we parse, catch up with narrowing/widening. */ 1506 /* Before we parse, catch up with narrowing/widening. */
1414 treesit_check_buffer_size (XBUFFER (XTS_PARSER (parser)->buffer)); 1507 treesit_check_buffer_size (XBUFFER (XTS_PARSER (parser)->buffer));
1415 treesit_ensure_position_synced (parser); 1508 treesit_sync_visible_region (parser);
1416 1509
1417 bool success; 1510 bool success;
1418 if (NILP (ranges)) 1511 if (NILP (ranges))
@@ -1439,9 +1532,9 @@ buffer. */)
1439 for (int idx = 0; !NILP (ranges); idx++, ranges = XCDR (ranges)) 1532 for (int idx = 0; !NILP (ranges); idx++, ranges = XCDR (ranges))
1440 { 1533 {
1441 Lisp_Object range = XCAR (ranges); 1534 Lisp_Object range = XCAR (ranges);
1442 EMACS_INT beg_byte = buf_charpos_to_bytepos (buffer, 1535 ptrdiff_t beg_byte = buf_charpos_to_bytepos (buffer,
1443 XFIXNUM (XCAR (range))); 1536 XFIXNUM (XCAR (range)));
1444 EMACS_INT end_byte = buf_charpos_to_bytepos (buffer, 1537 ptrdiff_t end_byte = buf_charpos_to_bytepos (buffer,
1445 XFIXNUM (XCDR (range))); 1538 XFIXNUM (XCDR (range)));
1446 /* Shouldn't violate assertion since we just checked for 1539 /* Shouldn't violate assertion since we just checked for
1447 buffer size at the beginning of this function. */ 1540 buffer size at the beginning of this function. */
@@ -1476,8 +1569,8 @@ DEFUN ("treesit-parser-included-ranges",
1476 Streesit_parser_included_ranges, 1569 Streesit_parser_included_ranges,
1477 1, 1, 0, 1570 1, 1, 0,
1478 doc: /* Return the ranges set for PARSER. 1571 doc: /* Return the ranges set for PARSER.
1479See `treesit-parser-set-ranges'. If no ranges are set for PARSER, 1572If no ranges are set for PARSER, return nil.
1480return nil. */) 1573See also `treesit-parser-set-included-ranges'. */)
1481 (Lisp_Object parser) 1574 (Lisp_Object parser)
1482{ 1575{
1483 treesit_check_parser (parser); 1576 treesit_check_parser (parser);
@@ -1498,7 +1591,7 @@ return nil. */)
1498 /* Our return value depends on the buffer state (BUF_BEGV_BYTE, 1591 /* Our return value depends on the buffer state (BUF_BEGV_BYTE,
1499 etc), so we need to sync up. */ 1592 etc), so we need to sync up. */
1500 treesit_check_buffer_size (XBUFFER (XTS_PARSER (parser)->buffer)); 1593 treesit_check_buffer_size (XBUFFER (XTS_PARSER (parser)->buffer));
1501 treesit_ensure_position_synced (parser); 1594 treesit_sync_visible_region (parser);
1502 1595
1503 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer); 1596 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
1504 return treesit_make_ranges (ranges, len, buffer); 1597 return treesit_make_ranges (ranges, len, buffer);
@@ -1580,6 +1673,17 @@ treesit_check_node (Lisp_Object obj)
1580 xsignal1 (Qtreesit_node_outdated, obj); 1673 xsignal1 (Qtreesit_node_outdated, obj);
1581} 1674}
1582 1675
1676/* Checks that OBJ is a positive integer and it is within the visible
1677 portion of BUF. */
1678static void
1679treesit_check_position (Lisp_Object obj, struct buffer *buf)
1680{
1681 treesit_check_positive_integer (obj);
1682 ptrdiff_t pos = XFIXNUM (obj);
1683 if (pos < BUF_BEGV (buf) || pos > BUF_ZV (buf))
1684 xsignal1 (Qargs_out_of_range, obj);
1685}
1686
1583bool 1687bool
1584treesit_node_uptodate_p (Lisp_Object obj) 1688treesit_node_uptodate_p (Lisp_Object obj)
1585{ 1689{
@@ -1658,6 +1762,8 @@ If NODE is nil, return nil. */)
1658 return build_string (string); 1762 return build_string (string);
1659} 1763}
1660 1764
1765static TSTreeCursor treesit_cursor_helper (TSNode, Lisp_Object);
1766
1661DEFUN ("treesit-node-parent", 1767DEFUN ("treesit-node-parent",
1662 Ftreesit_node_parent, Streesit_node_parent, 1, 1, 0, 1768 Ftreesit_node_parent, Streesit_node_parent, 1, 1, 0,
1663 doc: /* Return the immediate parent of NODE. 1769 doc: /* Return the immediate parent of NODE.
@@ -1668,13 +1774,18 @@ Return nil if NODE has no parent. If NODE is nil, return nil. */)
1668 treesit_check_node (node); 1774 treesit_check_node (node);
1669 treesit_initialize (); 1775 treesit_initialize ();
1670 1776
1671 TSNode treesit_node = XTS_NODE (node)->node; 1777 Lisp_Object return_value = Qnil;
1672 TSNode parent = ts_node_parent (treesit_node);
1673 1778
1674 if (ts_node_is_null (parent)) 1779 TSNode treesit_node = XTS_NODE (node)->node;
1675 return Qnil; 1780 Lisp_Object parser = XTS_NODE (node)->parser;
1676 1781 TSTreeCursor cursor = treesit_cursor_helper (treesit_node, parser);
1677 return make_treesit_node (XTS_NODE (node)->parser, parent); 1782 if (ts_tree_cursor_goto_parent (&cursor))
1783 {
1784 TSNode parent = ts_tree_cursor_current_node (&cursor);
1785 return_value = make_treesit_node (parser, parent);
1786 }
1787 ts_tree_cursor_delete (&cursor);
1788 return return_value;
1678} 1789}
1679 1790
1680DEFUN ("treesit-node-child", 1791DEFUN ("treesit-node-child",
@@ -1928,14 +2039,12 @@ Note that this function returns an immediate child, not the smallest
1928 if (NILP (node)) 2039 if (NILP (node))
1929 return Qnil; 2040 return Qnil;
1930 treesit_check_node (node); 2041 treesit_check_node (node);
1931 treesit_check_positive_integer (pos);
1932 2042
1933 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer); 2043 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer);
1934 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg; 2044 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
1935 ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos)); 2045 ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos));
1936 2046
1937 if (byte_pos < BUF_BEGV_BYTE (buf) || byte_pos > BUF_ZV_BYTE (buf)) 2047 treesit_check_position (pos, buf);
1938 xsignal1 (Qargs_out_of_range, pos);
1939 2048
1940 treesit_initialize (); 2049 treesit_initialize ();
1941 2050
@@ -1966,19 +2075,14 @@ If NODE is nil, return nil. */)
1966{ 2075{
1967 if (NILP (node)) return Qnil; 2076 if (NILP (node)) return Qnil;
1968 treesit_check_node (node); 2077 treesit_check_node (node);
1969 CHECK_INTEGER (beg);
1970 CHECK_INTEGER (end);
1971 2078
1972 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer); 2079 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer);
1973 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg; 2080 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
1974 ptrdiff_t byte_beg = buf_charpos_to_bytepos (buf, XFIXNUM (beg)); 2081 ptrdiff_t byte_beg = buf_charpos_to_bytepos (buf, XFIXNUM (beg));
1975 ptrdiff_t byte_end = buf_charpos_to_bytepos (buf, XFIXNUM (end)); 2082 ptrdiff_t byte_end = buf_charpos_to_bytepos (buf, XFIXNUM (end));
1976 2083
1977 /* Checks for BUFFER_BEG <= BEG <= END <= BUFFER_END. */ 2084 treesit_check_position (beg, buf);
1978 if (!(BUF_BEGV_BYTE (buf) <= byte_beg 2085 treesit_check_position (end, buf);
1979 && byte_beg <= byte_end
1980 && byte_end <= BUF_ZV_BYTE (buf)))
1981 xsignal2 (Qargs_out_of_range, beg, end);
1982 2086
1983 treesit_initialize (); 2087 treesit_initialize ();
1984 2088
@@ -2229,8 +2333,6 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures)
2229 2333
2230 Lisp_Object regexp = XCAR (args); 2334 Lisp_Object regexp = XCAR (args);
2231 Lisp_Object capture_name = XCAR (XCDR (args)); 2335 Lisp_Object capture_name = XCAR (XCDR (args));
2232 Lisp_Object text = treesit_predicate_capture_name_to_text (capture_name,
2233 captures);
2234 2336
2235 /* It's probably common to get the argument order backwards. Catch 2337 /* It's probably common to get the argument order backwards. Catch
2236 this mistake early and show helpful explanation, because Emacs 2338 this mistake early and show helpful explanation, because Emacs
@@ -2245,6 +2347,9 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures)
2245 build_pure_c_string ("The second argument to `match' should " 2347 build_pure_c_string ("The second argument to `match' should "
2246 "be a capture name, not a string")); 2348 "be a capture name, not a string"));
2247 2349
2350 Lisp_Object text = treesit_predicate_capture_name_to_text (capture_name,
2351 captures);
2352
2248 if (fast_string_match (regexp, text) >= 0) 2353 if (fast_string_match (regexp, text) >= 0)
2249 return true; 2354 return true;
2250 else 2355 else
@@ -2363,21 +2468,24 @@ the query. */)
2363 (Lisp_Object node, Lisp_Object query, 2468 (Lisp_Object node, Lisp_Object query,
2364 Lisp_Object beg, Lisp_Object end, Lisp_Object node_only) 2469 Lisp_Object beg, Lisp_Object end, Lisp_Object node_only)
2365{ 2470{
2366 if (!NILP (beg))
2367 CHECK_INTEGER (beg);
2368 if (!NILP (end))
2369 CHECK_INTEGER (end);
2370
2371 if (!(TS_COMPILED_QUERY_P (query) 2471 if (!(TS_COMPILED_QUERY_P (query)
2372 || CONSP (query) || STRINGP (query))) 2472 || CONSP (query) || STRINGP (query)))
2373 wrong_type_argument (Qtreesit_query_p, query); 2473 wrong_type_argument (Qtreesit_query_p, query);
2374 2474
2475 treesit_initialize ();
2476
2375 /* Resolve NODE into an actual node. */ 2477 /* Resolve NODE into an actual node. */
2376 Lisp_Object lisp_node; 2478 Lisp_Object lisp_node;
2377 if (TS_NODEP (node)) 2479 if (TS_NODEP (node))
2378 lisp_node = node; 2480 {
2481 treesit_check_node (node); /* Check if up-to-date. */
2482 lisp_node = node;
2483 }
2379 else if (TS_PARSERP (node)) 2484 else if (TS_PARSERP (node))
2380 lisp_node = Ftreesit_parser_root_node (node); 2485 {
2486 treesit_check_parser (node); /* Check if deleted. */
2487 lisp_node = Ftreesit_parser_root_node (node);
2488 }
2381 else if (SYMBOLP (node)) 2489 else if (SYMBOLP (node))
2382 { 2490 {
2383 Lisp_Object parser 2491 Lisp_Object parser
@@ -2389,8 +2497,6 @@ the query. */)
2389 list4 (Qor, Qtreesit_node_p, Qtreesit_parser_p, Qsymbolp), 2497 list4 (Qor, Qtreesit_node_p, Qtreesit_parser_p, Qsymbolp),
2390 node); 2498 node);
2391 2499
2392 treesit_initialize ();
2393
2394 /* Extract C values from Lisp objects. */ 2500 /* Extract C values from Lisp objects. */
2395 TSNode treesit_node 2501 TSNode treesit_node
2396 = XTS_NODE (lisp_node)->node; 2502 = XTS_NODE (lisp_node)->node;
@@ -2401,6 +2507,13 @@ the query. */)
2401 const TSLanguage *lang 2507 const TSLanguage *lang
2402 = ts_parser_language (XTS_PARSER (lisp_parser)->parser); 2508 = ts_parser_language (XTS_PARSER (lisp_parser)->parser);
2403 2509
2510 /* Check BEG and END. */
2511 struct buffer *buf = XBUFFER (XTS_PARSER (lisp_parser)->buffer);
2512 if (!NILP (beg))
2513 treesit_check_position (beg, buf);
2514 if (!NILP (end))
2515 treesit_check_position (end, buf);
2516
2404 /* Initialize query objects. At the end of this block, we should 2517 /* Initialize query objects. At the end of this block, we should
2405 have a working TSQuery and a TSQueryCursor. */ 2518 have a working TSQuery and a TSQueryCursor. */
2406 TSQuery *treesit_query; 2519 TSQuery *treesit_query;
@@ -2444,14 +2557,15 @@ the query. */)
2444 /* Set query range. */ 2557 /* Set query range. */
2445 if (!NILP (beg) && !NILP (end)) 2558 if (!NILP (beg) && !NILP (end))
2446 { 2559 {
2447 EMACS_INT beg_byte = XFIXNUM (beg); 2560 ptrdiff_t beg_byte = CHAR_TO_BYTE (XFIXNUM (beg));
2448 EMACS_INT end_byte = XFIXNUM (end); 2561 ptrdiff_t end_byte = CHAR_TO_BYTE (XFIXNUM (end));
2449 /* We never let tree-sitter run on buffers too large, so these 2562 /* We never let tree-sitter run on buffers too large, so these
2450 assertion should never hit. */ 2563 assertion should never hit. */
2451 eassert (beg_byte - visible_beg <= UINT32_MAX); 2564 eassert (beg_byte - visible_beg <= UINT32_MAX);
2452 eassert (end_byte - visible_beg <= UINT32_MAX); 2565 eassert (end_byte - visible_beg <= UINT32_MAX);
2453 ts_query_cursor_set_byte_range (cursor, (uint32_t) beg_byte - visible_beg, 2566 ts_query_cursor_set_byte_range (cursor,
2454 (uint32_t) end_byte - visible_beg); 2567 (uint32_t) (beg_byte - visible_beg),
2568 (uint32_t) (end_byte - visible_beg));
2455 } 2569 }
2456 2570
2457 /* Execute query. */ 2571 /* Execute query. */
@@ -2517,62 +2631,210 @@ the query. */)
2517 2631
2518/*** Navigation */ 2632/*** Navigation */
2519 2633
2520/* Return the next/previous named/unnamed sibling of NODE. FORWARD 2634static inline void
2521 controls the direction and NAMED controls the nameness. */ 2635treesit_assume_true (bool val)
2522static TSNode 2636{
2523treesit_traverse_sibling_helper (TSNode node, bool forward, bool named) 2637 eassert (val == true);
2638}
2639
2640/* Create a TSTreeCursor pointing at NODE. PARSER is the lisp parser
2641 that produced NODE.
2642
2643 The reason we need this instead of simply using ts_tree_cursor_new
2644 is that we have to create the cursor on the root node and traverse
2645 down to NODE, in order to record the correct stack of parent nodes.
2646 Otherwise going to sibling or parent of NODE wouldn't work.
2647
2648 (Wow perfect filling.) */
2649static TSTreeCursor
2650treesit_cursor_helper (TSNode node, Lisp_Object parser)
2651{
2652 uint32_t end_pos = ts_node_end_byte (node);
2653 TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree);
2654 TSTreeCursor cursor = ts_tree_cursor_new (root);
2655 TSNode cursor_node = ts_tree_cursor_current_node (&cursor);
2656 /* This is like treesit-node-at. We go down from the root node,
2657 either to first child or next sibling, repeatedly, and finally
2658 arrive at NODE. */
2659 while (!ts_node_eq (node, cursor_node))
2660 {
2661 treesit_assume_true (ts_tree_cursor_goto_first_child (&cursor));
2662 cursor_node = ts_tree_cursor_current_node (&cursor);
2663 /* ts_tree_cursor_goto_first_child_for_byte is not reliable, so
2664 we just go through each sibling. */
2665 while (ts_node_is_missing (cursor_node)
2666 || ts_node_end_byte (cursor_node) < end_pos)
2667 {
2668 /* A "missing" node has zero width, so it's possible that
2669 its end = NODE.end but it's not NODE, so we skip them.
2670 But we need to make sure this missing node is not the
2671 node we are looking for before skipping it. */
2672 if (ts_node_is_missing (cursor_node)
2673 && ts_node_eq (node, cursor_node))
2674 return cursor;
2675 treesit_assume_true (ts_tree_cursor_goto_next_sibling (&cursor));
2676 cursor_node = ts_tree_cursor_current_node (&cursor);
2677 }
2678 /* Right now CURSOR.end >= NODE.end. But what if CURSOR.end =
2679 NODE.end, and there are missing nodes after CURSOR, and the
2680 missing node after CURSOR is the NODE we are looking for??
2681 Well, create a probe and look ahead. (This is tested by
2682 treesit-cursor-helper-with-missing-node.) */
2683 TSTreeCursor probe = ts_tree_cursor_copy (&cursor);
2684 TSNode probe_node;
2685 while (ts_tree_cursor_goto_next_sibling (&probe))
2686 {
2687 probe_node = ts_tree_cursor_current_node (&probe);
2688 if (!ts_node_is_missing (probe_node))
2689 break;
2690 if (ts_node_eq (probe_node, node))
2691 {
2692 ts_tree_cursor_delete (&cursor);
2693 return probe;
2694 }
2695 }
2696 ts_tree_cursor_delete (&probe);
2697 }
2698 return cursor;
2699}
2700
2701/* Move CURSOR to the next/previous sibling. FORWARD controls the
2702 direction. NAMED controls the namedness. If there is a valid
2703 sibling, move CURSOR to it and return true, otherwise return false.
2704 When false is returned, CURSOR points to a sibling node of the node
2705 we started at, but exactly which is undefined. */
2706static bool
2707treesit_traverse_sibling_helper (TSTreeCursor *cursor,
2708 bool forward, bool named)
2524{ 2709{
2525 if (forward) 2710 if (forward)
2526 { 2711 {
2527 if (named) 2712 if (!named)
2528 return ts_node_next_named_sibling (node); 2713 return ts_tree_cursor_goto_next_sibling (cursor);
2529 else 2714 /* Else named... */
2530 return ts_node_next_sibling (node); 2715 while (ts_tree_cursor_goto_next_sibling (cursor))
2716 {
2717 if (ts_node_is_named (ts_tree_cursor_current_node (cursor)))
2718 return true;
2719 }
2720 return false;
2531 } 2721 }
2532 else 2722 else /* Backward. */
2533 { 2723 {
2534 if (named) 2724 /* Go to first child and go through each sibling, until we find
2535 return ts_node_prev_named_sibling (node); 2725 the one just before the starting node. */
2536 else 2726 TSNode start = ts_tree_cursor_current_node (cursor);
2537 return ts_node_prev_sibling (node); 2727 if (!ts_tree_cursor_goto_parent (cursor))
2728 return false;
2729 treesit_assume_true (ts_tree_cursor_goto_first_child (cursor));
2730
2731 /* Now CURSOR is at the first child. If we started at the first
2732 child, then there is no further siblings. */
2733 TSNode first_child = ts_tree_cursor_current_node (cursor);
2734 if (ts_node_eq (first_child, start))
2735 return false;
2736
2737 /* PROBE is always DELTA siblings ahead of CURSOR. */
2738 TSTreeCursor probe = ts_tree_cursor_copy (cursor);
2739 /* This is position of PROBE minus position of CURSOR. */
2740 ptrdiff_t delta = 0;
2741 TSNode probe_node;
2742 TSNode cursor_node;
2743 while (ts_tree_cursor_goto_next_sibling (&probe))
2744 {
2745 /* Move PROBE forward, if it equals to the starting node,
2746 CURSOR points to the node we want (prev valid sibling of
2747 the starting node). */
2748 delta++;
2749 probe_node = ts_tree_cursor_current_node (&probe);
2750
2751 /* PROBE matched, depending on NAMED, return true/false. */
2752 if (ts_node_eq (probe_node, start))
2753 {
2754 ts_tree_cursor_delete (&probe);
2755 cursor_node = ts_tree_cursor_current_node (cursor);
2756 ts_tree_cursor_delete (&probe);
2757 return (!named || (named && ts_node_is_named (cursor_node)));
2758 }
2759
2760 /* PROBE didn't match, move CURSOR forward to PROBE's
2761 position, but if we are looking for named nodes, only
2762 move CURSOR to PROBE if PROBE is at a named node. */
2763 if (!named || (named && ts_node_is_named (probe_node)))
2764 for (; delta > 0; delta--)
2765 treesit_assume_true (ts_tree_cursor_goto_next_sibling (cursor));
2766 }
2767 ts_tree_cursor_delete (&probe);
2768 return false;
2538 } 2769 }
2539} 2770}
2540 2771
2541/* Return the first/last named/unnamed child of NODE. FORWARD controls 2772/* Move CURSOR to the first/last child. FORWARD controls the
2542 the direction and NAMED controls the nameness. */ 2773 direction. NAMED controls the namedness. If there is a valid
2543static TSNode 2774 child, move CURSOR to it and return true, otherwise don't move
2544treesit_traverse_child_helper (TSNode node, bool forward, bool named) 2775 CURSOR and return false. */
2776static bool
2777treesit_traverse_child_helper (TSTreeCursor *cursor,
2778 bool forward, bool named)
2545{ 2779{
2546 if (forward) 2780 if (forward)
2547 { 2781 {
2548 if (named) 2782 if (!named)
2549 return ts_node_named_child (node, 0); 2783 return ts_tree_cursor_goto_first_child (cursor);
2550 else 2784 else
2551 return ts_node_child (node, 0);
2552 }
2553 else
2554 {
2555 if (named)
2556 { 2785 {
2557 uint32_t count = ts_node_named_child_count (node); 2786 if (!ts_tree_cursor_goto_first_child (cursor))
2558 uint32_t idx = count == 0 ? 0 : count - 1; 2787 return false;
2559 return ts_node_named_child (node, idx); 2788 /* After this point, if you return false, make sure to go
2789 back to parent. */
2790 TSNode first_child = ts_tree_cursor_current_node (cursor);
2791 if (ts_node_is_named (first_child))
2792 return true;
2793
2794 if (treesit_traverse_sibling_helper (cursor, true, true))
2795 return true;
2796 else
2797 {
2798 treesit_assume_true (ts_tree_cursor_goto_parent (cursor));
2799 return false;
2800 }
2560 } 2801 }
2802 }
2803 else /* Backward. */
2804 {
2805 if (!ts_tree_cursor_goto_first_child (cursor))
2806 return false;
2807 /* After this point, if you return false, make sure to go
2808 back to parent. */
2809
2810 /* First go to the last child. */
2811 while (ts_tree_cursor_goto_next_sibling (cursor));
2812
2813 if (!named)
2814 return true;
2815 /* Else named... */
2816 if (treesit_traverse_sibling_helper(cursor, false, true))
2817 return true;
2561 else 2818 else
2562 { 2819 {
2563 uint32_t count = ts_node_child_count (node); 2820 treesit_assume_true (ts_tree_cursor_goto_parent (cursor));
2564 uint32_t idx = count == 0 ? 0 : count - 1; 2821 return false;
2565 return ts_node_child (node, idx);
2566 } 2822 }
2567 } 2823 }
2568} 2824}
2569 2825
2570/* Return true if NODE matches PRED. PRED can be a string or a 2826/* Return true if the node at CURSOR matches PRED. PRED can be a
2571 function. This function doesn't check for PRED's type. */ 2827 string or a function. This function assumes PRED is either a
2828 string or a function. If NAMED is true, also check that the node
2829 is named. */
2572static bool 2830static bool
2573treesit_traverse_match_predicate (TSNode node, Lisp_Object pred, 2831treesit_traverse_match_predicate (TSTreeCursor *cursor, Lisp_Object pred,
2574 Lisp_Object parser) 2832 Lisp_Object parser, bool named)
2575{ 2833{
2834 TSNode node = ts_tree_cursor_current_node (cursor);
2835 if (named && !ts_node_is_named (node))
2836 return false;
2837
2576 if (STRINGP (pred)) 2838 if (STRINGP (pred))
2577 { 2839 {
2578 const char *type = ts_node_type (node); 2840 const char *type = ts_node_type (node);
@@ -2583,74 +2845,60 @@ treesit_traverse_match_predicate (TSNode node, Lisp_Object pred,
2583 Lisp_Object lisp_node = make_treesit_node (parser, node); 2845 Lisp_Object lisp_node = make_treesit_node (parser, node);
2584 return !NILP (CALLN (Ffuncall, pred, lisp_node)); 2846 return !NILP (CALLN (Ffuncall, pred, lisp_node));
2585 } 2847 }
2586
2587} 2848}
2588 2849
2589/* Traverse the parse tree starting from ROOT (but ROOT is not 2850/* Traverse the parse tree starting from CURSOR. PRED can be a
2590 matches against PRED). PRED can be a function (takes a node and 2851 function (takes a node and returns nil/non-nil), or a string
2591 returns nil/non-nil),or a string (treated as regexp matching the 2852 (treated as regexp matching the node's type, must be all single
2592 node's type, ignores case, must be all single byte characters). If 2853 byte characters). If the node satisfies PRED, leave CURSOR on that
2593 the node satisfies PRED , terminate, set ROOT to that node, and 2854 node and return true. If no node satisfies PRED, move CURSOR back
2594 return true. If no node satisfies PRED, return FALSE. PARSER is 2855 to starting position and return false.
2595 the parser of ROOT.
2596 2856
2597 LIMIT is the number of levels we descend in the tree. If NO_LIMIT 2857 LIMIT is the number of levels we descend in the tree. FORWARD
2598 is true, LIMIT is ignored. FORWARD controls the direction in which 2858 controls the direction in which we traverse the tree, true means
2599 we traverse the tree, true means forward, false backward. If NAMED 2859 forward, false backward. If SKIP_ROOT is true, don't match ROOT.
2600 is true, only traverse named nodes, if false, all nodes. If 2860 */
2601 SKIP_ROOT is true, don't match ROOT. */
2602static bool 2861static bool
2603treesit_search_dfs (TSNode *root, Lisp_Object pred, Lisp_Object parser, 2862treesit_search_dfs (TSTreeCursor *cursor,
2604 bool named, bool forward, ptrdiff_t limit, bool no_limit, 2863 Lisp_Object pred, Lisp_Object parser,
2864 bool forward, bool named, ptrdiff_t limit,
2605 bool skip_root) 2865 bool skip_root)
2606{ 2866{
2607 /* TSTreeCursor doesn't allow us to move backward, so we can't use 2867 if (!skip_root
2608 it. We could use limit == -1 to indicate no_limit == true, but 2868 && treesit_traverse_match_predicate (cursor, pred, parser, named))
2609 separating them is safer. */ 2869 return true;
2610 TSNode node = *root;
2611 2870
2612 if (!skip_root && treesit_traverse_match_predicate (node, pred, parser)) 2871 if (limit == 0)
2613 { 2872 return false;
2614 *root = node;
2615 return true;
2616 }
2617 2873
2618 if (!no_limit && limit <= 0) 2874 if (!treesit_traverse_child_helper (cursor, forward, named))
2619 return false; 2875 return false;
2620 else 2876 /* After this point, if you return false, make sure to go back to
2877 parent. */
2878
2879 do /* Iterate through each child. */
2621 { 2880 {
2622 int count = (named 2881 if (treesit_search_dfs (cursor, pred, parser, forward,
2623 ? ts_node_named_child_count (node) 2882 named, limit - 1, false))
2624 : ts_node_child_count (node)); 2883 return true;
2625 for (int offset = 0; offset < count; offset++)
2626 {
2627 uint32_t idx = forward ? offset : count - offset - 1;
2628 TSNode child = (named
2629 ? ts_node_named_child (node, idx)
2630 : ts_node_child (node, idx));
2631
2632 if (!ts_node_is_null (child)
2633 && treesit_search_dfs (&child, pred, parser, named,
2634 forward, limit - 1, no_limit, false))
2635 {
2636 *root = child;
2637 return true;
2638 }
2639 }
2640 return false;
2641 } 2884 }
2885 while (treesit_traverse_sibling_helper (cursor, forward, false));
2886
2887 /* No match in any child's subtree, go back to starting node. */
2888 treesit_assume_true (ts_tree_cursor_goto_parent (cursor));
2889 return false;
2642} 2890}
2643 2891
2644/* Go through the whole tree linearly, leaf-first, starting from 2892/* Go through the whole tree linearly, leaf-first, starting from
2645 START. PRED, PARSER, NAMED, FORWARD are the same as in 2893 START. PRED, PARSER, NAMED, FORWARD are the same as in
2646 ts_search_subtre. If UP_ONLY is true, never go to children, only 2894 ts_search_subtree. If a match is found, leave CURSOR at that node,
2647 sibling and parents. */ 2895 and return true, if no match is found, return false, and CURSOR's
2896 position is undefined. */
2648static bool 2897static bool
2649treesit_search_forward (TSNode *start, Lisp_Object pred, Lisp_Object parser, 2898treesit_search_forward (TSTreeCursor *cursor,
2650 bool named, bool forward) 2899 Lisp_Object pred, Lisp_Object parser,
2900 bool forward, bool named)
2651{ 2901{
2652 TSNode node = *start;
2653
2654 /* We don't search for subtree and always search from the leaf 2902 /* We don't search for subtree and always search from the leaf
2655 nodes. This way repeated call of this function traverses each 2903 nodes. This way repeated call of this function traverses each
2656 node in the tree once and only once: 2904 node in the tree once and only once:
@@ -2660,39 +2908,26 @@ treesit_search_forward (TSNode *start, Lisp_Object pred, Lisp_Object parser,
2660 bool initial = true; 2908 bool initial = true;
2661 while (true) 2909 while (true)
2662 { 2910 {
2663 if (!initial /* We don't match START. */ 2911 if (!initial /* We don't match the starting node. */
2664 && treesit_traverse_match_predicate (node, pred, parser)) 2912 && treesit_traverse_match_predicate (cursor, pred, parser, named))
2665 { 2913 return true;
2666 *start = node;
2667 return true;
2668 }
2669 initial = false; 2914 initial = false;
2670 2915
2671 TSNode next = treesit_traverse_sibling_helper (node, forward, named); 2916 /* Try going to the next sibling, if there is no next sibling,
2672 while (ts_node_is_null (next)) 2917 go to parent and try again. */
2918 while (!treesit_traverse_sibling_helper (cursor, forward, named))
2673 { 2919 {
2674 /* There is no next sibling, go to parent. */ 2920 /* There is no next sibling, go to parent. */
2675 node = ts_node_parent (node); 2921 if (!ts_tree_cursor_goto_parent (cursor))
2676 if (ts_node_is_null (node))
2677 return false; 2922 return false;
2678 2923
2679 if (treesit_traverse_match_predicate (node, pred, parser)) 2924 if (treesit_traverse_match_predicate (cursor, pred, parser, named))
2680 {
2681 *start = node;
2682 return true; 2925 return true;
2683 }
2684 next = treesit_traverse_sibling_helper (node, forward, named);
2685 } 2926 }
2686 /* We are at the next sibling, deep dive into the first leaf 2927 /* We are at the next sibling, deep dive into the first leaf
2687 node. */ 2928 node. */
2688 TSNode next_next = treesit_traverse_child_helper (next, forward, named); 2929 while (treesit_traverse_child_helper (cursor, forward, false));
2689 while (!ts_node_is_null (next_next)) 2930 /* At this point CURSOR is at a leaf node. */
2690 {
2691 next = next_next;
2692 next_next = treesit_traverse_child_helper (next, forward, named);
2693 }
2694 /* At this point NEXT is a leaf node. */
2695 node = next;
2696 } 2931 }
2697} 2932}
2698 2933
@@ -2707,7 +2942,8 @@ node's type, or a function that takes a node and returns nil/non-nil.
2707 2942
2708By default, only traverse named nodes, but if ALL is non-nil, traverse 2943By default, only traverse named nodes, but if ALL is non-nil, traverse
2709all nodes. If BACKWARD is non-nil, traverse backwards. If LIMIT is 2944all nodes. If BACKWARD is non-nil, traverse backwards. If LIMIT is
2710non-nil, only traverse nodes up to that number of levels down in the tree. 2945non-nil, only traverse nodes up to that number of levels down in the
2946tree. If LIMIT is nil, default to 1000.
2711 2947
2712Return the first matched node, or nil if none matches. */) 2948Return the first matched node, or nil if none matches. */)
2713 (Lisp_Object node, Lisp_Object predicate, Lisp_Object backward, 2949 (Lisp_Object node, Lisp_Object predicate, Lisp_Object backward,
@@ -2719,11 +2955,10 @@ Return the first matched node, or nil if none matches. */)
2719 CHECK_SYMBOL (all); 2955 CHECK_SYMBOL (all);
2720 CHECK_SYMBOL (backward); 2956 CHECK_SYMBOL (backward);
2721 2957
2722 ptrdiff_t the_limit = 0; 2958 /* We use a default limit of 1000. See bug#59426 for the
2723 bool no_limit = false; 2959 discussion. */
2724 if (NILP (limit)) 2960 ptrdiff_t the_limit = 1000;
2725 no_limit = true; 2961 if (!NILP (limit))
2726 else
2727 { 2962 {
2728 CHECK_FIXNUM (limit); 2963 CHECK_FIXNUM (limit);
2729 the_limit = XFIXNUM (limit); 2964 the_limit = XFIXNUM (limit);
@@ -2731,13 +2966,17 @@ Return the first matched node, or nil if none matches. */)
2731 2966
2732 treesit_initialize (); 2967 treesit_initialize ();
2733 2968
2734 TSNode treesit_node = XTS_NODE (node)->node;
2735 Lisp_Object parser = XTS_NODE (node)->parser; 2969 Lisp_Object parser = XTS_NODE (node)->parser;
2736 if (treesit_search_dfs (&treesit_node, predicate, parser, NILP (all), 2970 Lisp_Object return_value = Qnil;
2737 NILP (backward), the_limit, no_limit, false)) 2971 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (node)->node, parser);
2738 return make_treesit_node (parser, treesit_node); 2972 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward),
2739 else 2973 NILP (all), the_limit, false))
2740 return Qnil; 2974 {
2975 TSNode node = ts_tree_cursor_current_node (&cursor);
2976 return_value = make_treesit_node (parser, node);
2977 }
2978 ts_tree_cursor_delete (&cursor);
2979 return return_value;
2741} 2980}
2742 2981
2743DEFUN ("treesit-search-forward", 2982DEFUN ("treesit-search-forward",
@@ -2781,13 +3020,17 @@ always traverse leaf nodes first, then upwards. */)
2781 3020
2782 treesit_initialize (); 3021 treesit_initialize ();
2783 3022
2784 TSNode treesit_start = XTS_NODE (start)->node;
2785 Lisp_Object parser = XTS_NODE (start)->parser; 3023 Lisp_Object parser = XTS_NODE (start)->parser;
2786 if (treesit_search_forward (&treesit_start, predicate, parser, NILP (all), 3024 Lisp_Object return_value = Qnil;
2787 NILP (backward))) 3025 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (start)->node, parser);
2788 return make_treesit_node (parser, treesit_start); 3026 if (treesit_search_forward (&cursor, predicate, parser,
2789 else 3027 NILP (backward), NILP (all)))
2790 return Qnil; 3028 {
3029 TSNode node = ts_tree_cursor_current_node (&cursor);
3030 return_value = make_treesit_node (parser, node);
3031 }
3032 ts_tree_cursor_delete (&cursor);
3033 return return_value;
2791} 3034}
2792 3035
2793/* Recursively traverse the tree under CURSOR, and append the result 3036/* Recursively traverse the tree under CURSOR, and append the result
@@ -2797,15 +3040,14 @@ always traverse leaf nodes first, then upwards. */)
2797static void 3040static void
2798treesit_build_sparse_tree (TSTreeCursor *cursor, Lisp_Object parent, 3041treesit_build_sparse_tree (TSTreeCursor *cursor, Lisp_Object parent,
2799 Lisp_Object pred, Lisp_Object process_fn, 3042 Lisp_Object pred, Lisp_Object process_fn,
2800 ptrdiff_t limit, bool no_limit, Lisp_Object parser) 3043 ptrdiff_t limit, Lisp_Object parser)
2801{ 3044{
2802 3045 bool match = treesit_traverse_match_predicate (cursor, pred, parser, false);
2803 TSNode node = ts_tree_cursor_current_node (cursor);
2804 bool match = treesit_traverse_match_predicate (node, pred, parser);
2805 if (match) 3046 if (match)
2806 { 3047 {
2807 /* If this node matches pred, add a new node to the parent's 3048 /* If this node matches pred, add a new node to the parent's
2808 children list. */ 3049 children list. */
3050 TSNode node = ts_tree_cursor_current_node (cursor);
2809 Lisp_Object lisp_node = make_treesit_node (parser, node); 3051 Lisp_Object lisp_node = make_treesit_node (parser, node);
2810 if (!NILP (process_fn)) 3052 if (!NILP (process_fn))
2811 lisp_node = CALLN (Ffuncall, process_fn, lisp_node); 3053 lisp_node = CALLN (Ffuncall, process_fn, lisp_node);
@@ -2816,8 +3058,7 @@ treesit_build_sparse_tree (TSTreeCursor *cursor, Lisp_Object parent,
2816 parent = this; 3058 parent = this;
2817 } 3059 }
2818 /* Go through each child. */ 3060 /* Go through each child. */
2819 if ((no_limit || limit > 0) 3061 if (limit > 0 && ts_tree_cursor_goto_first_child (cursor))
2820 && ts_tree_cursor_goto_first_child (cursor))
2821 { 3062 {
2822 do 3063 do
2823 { 3064 {
@@ -2825,7 +3066,7 @@ treesit_build_sparse_tree (TSTreeCursor *cursor, Lisp_Object parent,
2825 Then C compilers should be smart enough not to copy NODE 3066 Then C compilers should be smart enough not to copy NODE
2826 to stack. */ 3067 to stack. */
2827 treesit_build_sparse_tree (cursor, parent, pred, process_fn, 3068 treesit_build_sparse_tree (cursor, parent, pred, process_fn,
2828 limit - 1, no_limit, parser); 3069 limit - 1, parser);
2829 } 3070 }
2830 while (ts_tree_cursor_goto_next_sibling (cursor)); 3071 while (ts_tree_cursor_goto_next_sibling (cursor));
2831 /* Don't forget to come back to this node. */ 3072 /* Don't forget to come back to this node. */
@@ -2866,7 +3107,8 @@ If PROCESS-FN is non-nil, it should be a function of one argument. In
2866that case, instead of returning the matched nodes, pass each node to 3107that case, instead of returning the matched nodes, pass each node to
2867PROCESS-FN, and use its return value instead. 3108PROCESS-FN, and use its return value instead.
2868 3109
2869If non-nil, LIMIT is the number of levels to go down the tree from ROOT. 3110If non-nil, LIMIT is the number of levels to go down the tree from
3111ROOT. If LIMIT is nil or omitted, it defaults to 1000.
2870 3112
2871Each node in the returned tree looks like (NODE . (CHILD ...)). The 3113Each node in the returned tree looks like (NODE . (CHILD ...)). The
2872root of this tree might be nil, if ROOT doesn't match PREDICATE. 3114root of this tree might be nil, if ROOT doesn't match PREDICATE.
@@ -2885,11 +3127,11 @@ a regexp. */)
2885 3127
2886 if (!NILP (process_fn)) 3128 if (!NILP (process_fn))
2887 CHECK_TYPE (FUNCTIONP (process_fn), Qfunctionp, process_fn); 3129 CHECK_TYPE (FUNCTIONP (process_fn), Qfunctionp, process_fn);
2888 ptrdiff_t the_limit = 0; 3130
2889 bool no_limit = false; 3131 /* We use a default limit of 1000. See bug#59426 for the
2890 if (NILP (limit)) 3132 discussion. */
2891 no_limit = true; 3133 ptrdiff_t the_limit = 1000;
2892 else 3134 if (!NILP (limit))
2893 { 3135 {
2894 CHECK_FIXNUM (limit); 3136 CHECK_FIXNUM (limit);
2895 the_limit = XFIXNUM (limit); 3137 the_limit = XFIXNUM (limit);
@@ -2897,11 +3139,12 @@ a regexp. */)
2897 3139
2898 treesit_initialize (); 3140 treesit_initialize ();
2899 3141
2900 TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (root)->node);
2901 Lisp_Object parser = XTS_NODE (root)->parser; 3142 Lisp_Object parser = XTS_NODE (root)->parser;
2902 Lisp_Object parent = Fcons (Qnil, Qnil); 3143 Lisp_Object parent = Fcons (Qnil, Qnil);
3144 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (root)->node, parser);
2903 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn, 3145 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn,
2904 the_limit, no_limit, parser); 3146 the_limit, parser);
3147 ts_tree_cursor_delete (&cursor);
2905 Fsetcdr (parent, Fnreverse (Fcdr (parent))); 3148 Fsetcdr (parent, Fnreverse (Fcdr (parent)));
2906 if (NILP (Fcdr (parent))) 3149 if (NILP (Fcdr (parent)))
2907 return Qnil; 3150 return Qnil;
diff --git a/src/treesit.h b/src/treesit.h
index 1473126c5bc..6f6423ff472 100644
--- a/src/treesit.h
+++ b/src/treesit.h
@@ -56,13 +56,12 @@ struct Lisp_TS_Parser
56 this field to true to force tree-sitter to re-parse. */ 56 this field to true to force tree-sitter to re-parse. */
57 bool need_reparse; 57 bool need_reparse;
58 /* These two positions record the buffer byte position (1-based) of 58 /* These two positions record the buffer byte position (1-based) of
59 the "visible region" that tree-sitter sees. Unlike markers, 59 the "visible region" that tree-sitter sees. Before re-parse, we
60 These two positions do not change as the user inserts and deletes 60 move these positions to match BUF_BEGV_BYTE and BUF_ZV_BYTE.
61 text around them. Before re-parse, we move these positions to 61 Note that we don't need to synchronize these positions when
62 match BUF_BEGV_BYTE and BUF_ZV_BYTE. Note that we don't need to 62 retrieving them in a function that involves a node: if the node
63 synchronize these positions when retrieving them in a function 63 is not outdated, these positions are synchronized. See comment
64 that involves a node: if the node is not outdated, these 64 (ref:visible-beg-null) in treesit.c for more explanation. */
65 positions are synchronized. */
66 ptrdiff_t visible_beg; 65 ptrdiff_t visible_beg;
67 ptrdiff_t visible_end; 66 ptrdiff_t visible_end;
68 /* This counter is incremented every time a change is made to the 67 /* This counter is incremented every time a change is made to the
diff --git a/src/window.c b/src/window.c
index f116b9a9d72..90fa6ac2dfe 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2639,7 +2639,7 @@ window_list (void)
2639 Lisp_Object arglist = Qnil; 2639 Lisp_Object arglist = Qnil;
2640 2640
2641 /* We are visiting windows in canonical order, and add 2641 /* We are visiting windows in canonical order, and add
2642 new windows at the front of args[1], which means we 2642 new windows at the front of arglist, which means we
2643 have to reverse this list at the end. */ 2643 have to reverse this list at the end. */
2644 foreach_window (XFRAME (frame), add_window_to_list, &arglist); 2644 foreach_window (XFRAME (frame), add_window_to_list, &arglist);
2645 arglist = Fnreverse (arglist); 2645 arglist = Fnreverse (arglist);
@@ -7329,6 +7329,14 @@ the return value is nil. Otherwise the value is t. */)
7329 last_selected_window) 7329 last_selected_window)
7330 = selected_window; 7330 = selected_window;
7331 7331
7332 /* We may have deleted windows above. Then again, maybe we
7333 haven't: the functions we call to maybe delete windows can
7334 decide a window cannot be deleted. Force recalculation of
7335 Vwindow_list next time it is needed, to make sure stale
7336 windows with no buffers don't escape into the wild, which
7337 will cause crashes elsewhere. */
7338 Vwindow_list = Qnil;
7339
7332 if (NILP (data->focus_frame) 7340 if (NILP (data->focus_frame)
7333 || (FRAMEP (data->focus_frame) 7341 || (FRAMEP (data->focus_frame)
7334 && FRAME_LIVE_P (XFRAME (data->focus_frame)))) 7342 && FRAME_LIVE_P (XFRAME (data->focus_frame))))
diff --git a/src/xdisp.c b/src/xdisp.c
index 5dcf21dc4ce..e8df230ef89 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3533,6 +3533,33 @@ get_closer_narrowed_begv (struct window *w, ptrdiff_t pos)
3533 return max ((pos / len - 1) * len, BEGV); 3533 return max ((pos / len - 1) * len, BEGV);
3534} 3534}
3535 3535
3536ptrdiff_t
3537get_locked_narrowing_begv (ptrdiff_t pos)
3538{
3539 if (long_line_locked_narrowing_region_size <= 0)
3540 return BEGV;
3541 int len = long_line_locked_narrowing_region_size / 2;
3542 int begv = max (pos - len, BEGV);
3543 int limit = long_line_locked_narrowing_bol_search_limit;
3544 while (limit > 0)
3545 {
3546 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3547 return begv;
3548 begv--;
3549 limit--;
3550 }
3551 return begv;
3552}
3553
3554ptrdiff_t
3555get_locked_narrowing_zv (ptrdiff_t pos)
3556{
3557 if (long_line_locked_narrowing_region_size <= 0)
3558 return ZV;
3559 int len = long_line_locked_narrowing_region_size / 2;
3560 return min (pos + len, ZV);
3561}
3562
3536static void 3563static void
3537unwind_narrowed_begv (Lisp_Object point_min) 3564unwind_narrowed_begv (Lisp_Object point_min)
3538{ 3565{
@@ -4366,18 +4393,20 @@ handle_fontified_prop (struct it *it)
4366 4393
4367 eassert (it->end_charpos == ZV); 4394 eassert (it->end_charpos == ZV);
4368 4395
4369 if (current_buffer->long_line_optimizations_p) 4396 if (current_buffer->long_line_optimizations_p
4397 && long_line_locked_narrowing_region_size > 0)
4370 { 4398 {
4371 ptrdiff_t begv = it->narrowed_begv; 4399 ptrdiff_t begv = it->locked_narrowing_begv;
4372 ptrdiff_t zv = it->narrowed_zv; 4400 ptrdiff_t zv = it->locked_narrowing_zv;
4373 ptrdiff_t charpos = IT_CHARPOS (*it); 4401 ptrdiff_t charpos = IT_CHARPOS (*it);
4374 if (charpos < begv || charpos > zv) 4402 if (charpos < begv || charpos > zv)
4375 { 4403 {
4376 begv = get_narrowed_begv (it->w, charpos); 4404 begv = get_locked_narrowing_begv (charpos);
4377 zv = get_narrowed_zv (it->w, charpos); 4405 zv = get_locked_narrowing_zv (charpos);
4378 } 4406 }
4379 narrow_to_region_internal (make_fixnum (begv), make_fixnum (zv), true); 4407 if (begv != BEG || zv != Z)
4380 specbind (Qrestrictions_locked, Qt); 4408 narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
4409 Qfontification_functions);
4381 } 4410 }
4382 4411
4383 /* Don't allow Lisp that runs from 'fontification-functions' 4412 /* Don't allow Lisp that runs from 'fontification-functions'
@@ -6252,13 +6281,16 @@ static ptrdiff_t
6252string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos) 6281string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6253{ 6282{
6254 const int MAX_DISTANCE = 1000; 6283 const int MAX_DISTANCE = 1000;
6284 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6255 ptrdiff_t found = string_buffer_position_lim (string, around_charpos, 6285 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6256 around_charpos + MAX_DISTANCE, 6286 forward_limit, false);
6257 false);
6258 6287
6259 if (!found) 6288 if (!found)
6260 found = string_buffer_position_lim (string, around_charpos, 6289 {
6261 around_charpos - MAX_DISTANCE, true); 6290 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6291 found = string_buffer_position_lim (string, around_charpos,
6292 backward_limit, true);
6293 }
6262 return found; 6294 return found;
6263} 6295}
6264 6296
@@ -7435,12 +7467,20 @@ reseat (struct it *it, struct text_pos pos, bool force_p)
7435 { 7467 {
7436 it->narrowed_begv = get_narrowed_begv (it->w, window_point (it->w)); 7468 it->narrowed_begv = get_narrowed_begv (it->w, window_point (it->w));
7437 it->narrowed_zv = get_narrowed_zv (it->w, window_point (it->w)); 7469 it->narrowed_zv = get_narrowed_zv (it->w, window_point (it->w));
7470 it->locked_narrowing_begv
7471 = get_locked_narrowing_begv (window_point (it->w));
7472 it->locked_narrowing_zv
7473 = get_locked_narrowing_zv (window_point (it->w));
7438 } 7474 }
7439 else if ((pos.charpos < it->narrowed_begv || pos.charpos > it->narrowed_zv) 7475 else if ((pos.charpos < it->narrowed_begv || pos.charpos > it->narrowed_zv)
7440 && (!redisplaying_p || it->line_wrap == TRUNCATE)) 7476 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7441 { 7477 {
7442 it->narrowed_begv = get_narrowed_begv (it->w, pos.charpos); 7478 it->narrowed_begv = get_narrowed_begv (it->w, pos.charpos);
7443 it->narrowed_zv = get_narrowed_zv (it->w, pos.charpos); 7479 it->narrowed_zv = get_narrowed_zv (it->w, pos.charpos);
7480 it->locked_narrowing_begv
7481 = get_locked_narrowing_begv (window_point (it->w));
7482 it->locked_narrowing_zv
7483 = get_locked_narrowing_zv (window_point (it->w));
7444 } 7484 }
7445 } 7485 }
7446 7486
@@ -16266,7 +16306,6 @@ do { if (! polling_stopped_here) stop_polling (); \
16266do { if (polling_stopped_here) start_polling (); \ 16306do { if (polling_stopped_here) start_polling (); \
16267 polling_stopped_here = false; } while (false) 16307 polling_stopped_here = false; } while (false)
16268 16308
16269
16270/* Perhaps in the future avoid recentering windows if it 16309/* Perhaps in the future avoid recentering windows if it
16271 is not necessary; currently that causes some problems. */ 16310 is not necessary; currently that causes some problems. */
16272 16311
@@ -16352,6 +16391,8 @@ redisplay_internal (void)
16352 FOR_EACH_FRAME (tail, frame) 16391 FOR_EACH_FRAME (tail, frame)
16353 XFRAME (frame)->already_hscrolled_p = false; 16392 XFRAME (frame)->already_hscrolled_p = false;
16354 16393
16394 reset_outermost_narrowings ();
16395
16355 retry: 16396 retry:
16356 /* Remember the currently selected window. */ 16397 /* Remember the currently selected window. */
16357 sw = w; 16398 sw = w;
@@ -17226,7 +17267,6 @@ mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17226 17267
17227 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b); 17268 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17228 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b); 17269 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17229 BUF_CHARS_UNCHANGED_MODIFIED (b) = BUF_CHARS_MODIFF (b);
17230 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b); 17270 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17231 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b); 17271 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17232 17272
@@ -19392,6 +19432,13 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
19392 blank_row (w, row, y); 19432 blank_row (w, row, y);
19393 goto finish_scroll_bars; 19433 goto finish_scroll_bars;
19394 } 19434 }
19435 else if (minibuf_level >= 1)
19436 {
19437 /* We could have a message produced by set-minibuffer-message
19438 displayed in the mini-window as an overlay, so resize the
19439 mini-window if needed. */
19440 resize_mini_window (w, false);
19441 }
19395 19442
19396 clear_glyph_matrix (w->desired_matrix); 19443 clear_glyph_matrix (w->desired_matrix);
19397 } 19444 }
@@ -19497,7 +19544,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
19497 /* Check whether the buffer to be displayed contains long lines. */ 19544 /* Check whether the buffer to be displayed contains long lines. */
19498 if (!NILP (Vlong_line_threshold) 19545 if (!NILP (Vlong_line_threshold)
19499 && !current_buffer->long_line_optimizations_p 19546 && !current_buffer->long_line_optimizations_p
19500 && CHARS_MODIFF - CHARS_UNCHANGED_MODIFIED > 8) 19547 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19548 || current_buffer->clip_changed))
19501 { 19549 {
19502 ptrdiff_t cur, next, found, max = 0, threshold; 19550 ptrdiff_t cur, next, found, max = 0, threshold;
19503 threshold = XFIXNUM (Vlong_line_threshold); 19551 threshold = XFIXNUM (Vlong_line_threshold);
@@ -22578,7 +22626,8 @@ usage: (trace-to-stderr STRING &rest OBJECTS) */)
22578 ***********************************************************************/ 22626 ***********************************************************************/
22579 22627
22580/* Return a temporary glyph row holding the glyphs of an overlay arrow. 22628/* Return a temporary glyph row holding the glyphs of an overlay arrow.
22581 Used for non-window-redisplay windows, and for windows w/o left fringe. */ 22629 Used for non-window-redisplay windows, and for windows without left
22630 fringe. */
22582 22631
22583static struct glyph_row * 22632static struct glyph_row *
22584get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) 22633get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
@@ -26272,16 +26321,17 @@ display_menu_bar (struct window *w)
26272 it.first_visible_x = 0; 26321 it.first_visible_x = 0;
26273 it.last_visible_x = FRAME_PIXEL_WIDTH (f); 26322 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26274#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */ 26323#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
26324 struct window *menu_window = NULL;
26325 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26326
26275 if (FRAME_WINDOW_P (f)) 26327 if (FRAME_WINDOW_P (f))
26276 { 26328 {
26277 /* Menu bar lines are displayed in the desired matrix of the 26329 /* Menu bar lines are displayed in the desired matrix of the
26278 dummy window menu_bar_window. */ 26330 dummy window menu_bar_window. */
26279 struct window *menu_w; 26331 menu_window = XWINDOW (f->menu_bar_window);
26280 menu_w = XWINDOW (f->menu_bar_window); 26332 init_iterator (&it, menu_window, -1, -1,
26281 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows, 26333 menu_window->desired_matrix->rows,
26282 MENU_FACE_ID); 26334 MENU_FACE_ID);
26283 it.first_visible_x = 0;
26284 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26285 } 26335 }
26286 else 26336 else
26287#endif /* not USE_X_TOOLKIT and not USE_GTK */ 26337#endif /* not USE_X_TOOLKIT and not USE_GTK */
@@ -26335,6 +26385,50 @@ display_menu_bar (struct window *w)
26335 26385
26336 /* Compute the total height of the lines. */ 26386 /* Compute the total height of the lines. */
26337 compute_line_metrics (&it); 26387 compute_line_metrics (&it);
26388 it.glyph_row->full_width_p = true;
26389 it.glyph_row->continued_p = false;
26390 it.glyph_row->truncated_on_left_p = false;
26391 it.glyph_row->truncated_on_right_p = false;
26392
26393#if defined (HAVE_X_WINDOWS) && !defined (USE_X_TOOLKIT) && !defined (USE_GTK)
26394 /* Make a 3D menu bar have a shadow at its right end. */
26395 extend_face_to_end_of_line (&it);
26396 if (face->box != FACE_NO_BOX)
26397 {
26398 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26399 + it.glyph_row->used[TEXT_AREA] - 1);
26400 int box_thickness = face->box_vertical_line_width;
26401 last->right_box_line_p = true;
26402 /* Add back the space for the right box line we subtracted in
26403 init_iterator, since the right_box_line_p flag will make the
26404 glyph wider. We actually add only as much space as is
26405 available for the last glyph of the menu bar and whatever
26406 space is left beyond it, since that glyph could be only
26407 partially visible. */
26408 if (box_thickness > 0)
26409 last->pixel_width += max (0, (box_thickness
26410 - (it.current_x - it.last_visible_x)));
26411 }
26412
26413 /* With the non-toolkit version, modify the menu bar window height
26414 accordingly. */
26415 if (FRAME_WINDOW_P (it.f) && menu_window)
26416 {
26417 struct glyph_row *row;
26418 int delta_height;
26419
26420 row = it.glyph_row;
26421 delta_height
26422 = ((row->y + row->height)
26423 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26424
26425 if (delta_height != 0)
26426 {
26427 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26428 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26429 }
26430 }
26431#endif
26338} 26432}
26339 26433
26340/* Deep copy of a glyph row, including the glyphs. */ 26434/* Deep copy of a glyph row, including the glyphs. */
@@ -36711,10 +36805,11 @@ fontify a region starting at POS in the current buffer, and give
36711fontified regions the property `fontified' with a non-nil value. 36805fontified regions the property `fontified' with a non-nil value.
36712 36806
36713Note that, when the buffer contains one or more lines whose length is 36807Note that, when the buffer contains one or more lines whose length is
36714above `long-line-threshold', these functions are called with the buffer 36808above `long-line-threshold', these functions are called with the
36715narrowed to a small portion around POS, and the narrowing is locked (see 36809buffer narrowed to a small portion around POS (whose size is specified
36716`narrow-to-region'), so that these functions cannot use `widen' to gain 36810by `long-line-locked-narrowing-region-size'), and the narrowing is
36717access to other portions of buffer text. */); 36811locked (see `narrowing-lock'), so that these functions cannot use
36812`widen' to gain access to other portions of buffer text. */);
36718 Vfontification_functions = Qnil; 36813 Vfontification_functions = Qnil;
36719 Fmake_variable_buffer_local (Qfontification_functions); 36814 Fmake_variable_buffer_local (Qfontification_functions);
36720 36815
diff --git a/src/xfaces.c b/src/xfaces.c
index df078227c8a..be4a7ca71cc 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -6014,6 +6014,23 @@ realize_non_ascii_face (struct frame *f, Lisp_Object font_object,
6014} 6014}
6015#endif /* HAVE_WINDOW_SYSTEM */ 6015#endif /* HAVE_WINDOW_SYSTEM */
6016 6016
6017/* Remove the attribute at INDEX from the font object if SYMBOL
6018 appears in `font-fallback-ignored-attributes'. */
6019
6020static void
6021font_maybe_unset_attribute (Lisp_Object font_object,
6022 enum font_property_index index, Lisp_Object symbol)
6023{
6024 Lisp_Object tail = Vface_font_lax_matched_attributes;
6025
6026 eassert (CONSP (tail));
6027
6028 FOR_EACH_TAIL_SAFE (tail)
6029 {
6030 if (EQ (XCAR (tail), symbol))
6031 ASET (font_object, index, Qnil);
6032 }
6033}
6017 6034
6018/* Realize the fully-specified face with attributes ATTRS in face 6035/* Realize the fully-specified face with attributes ATTRS in face
6019 cache CACHE for ASCII characters. Do it for GUI frame CACHE->f. 6036 cache CACHE for ASCII characters. Do it for GUI frame CACHE->f.
@@ -6071,8 +6088,48 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE]
6071 emacs_abort (); 6088 emacs_abort ();
6072 } 6089 }
6073 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) 6090 if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
6074 attrs[LFACE_FONT_INDEX] 6091 {
6075 = font_load_for_lface (f, attrs, attrs[LFACE_FONT_INDEX]); 6092 Lisp_Object spec = copy_font_spec (attrs[LFACE_FONT_INDEX]);
6093
6094 /* Maybe unset several values in SPEC, usually the width,
6095 slant, and weight. The best possible values for these
6096 attributes are determined in font_find_for_lface, called
6097 by font_load_for_lface, when the list of candidate fonts
6098 returned by font_list_entities is sorted by font_select_entity
6099 (which calls font_sort_entities, which calls font_score).
6100 If these attributes are not unset here, the candidate
6101 font list returned by font_list_entities only contains
6102 fonts that are exact matches for these weight, slant, and
6103 width attributes, which could lead to suboptimal or wrong
6104 font selection. (bug#5934) */
6105 if (EQ (Vface_font_lax_matched_attributes, Qt))
6106 {
6107 /* The default case: clear the font attributes that
6108 affect its appearance the least, to try to find some
6109 font that is close, if not exact, match. */
6110 ASET (spec, FONT_WEIGHT_INDEX, Qnil);
6111 ASET (spec, FONT_SLANT_INDEX, Qnil);
6112 ASET (spec, FONT_WIDTH_INDEX, Qnil);
6113 }
6114 else if (!NILP (Vface_font_lax_matched_attributes))
6115 {
6116 /* Also allow unsetting specific attributes for
6117 debugging purposes. */
6118 font_maybe_unset_attribute (spec, FONT_WEIGHT_INDEX, QCweight);
6119 font_maybe_unset_attribute (spec, FONT_SLANT_INDEX, QCslant);
6120 font_maybe_unset_attribute (spec, FONT_WIDTH_INDEX, QCwidth);
6121 font_maybe_unset_attribute (spec, FONT_FAMILY_INDEX, QCfamily);
6122 font_maybe_unset_attribute (spec, FONT_FOUNDRY_INDEX, QCfoundry);
6123 font_maybe_unset_attribute (spec, FONT_REGISTRY_INDEX, QCregistry);
6124 font_maybe_unset_attribute (spec, FONT_ADSTYLE_INDEX, QCadstyle);
6125 font_maybe_unset_attribute (spec, FONT_SIZE_INDEX, QCsize);
6126 font_maybe_unset_attribute (spec, FONT_DPI_INDEX, QCdpi);
6127 font_maybe_unset_attribute (spec, FONT_SPACING_INDEX, QCspacing);
6128 font_maybe_unset_attribute (spec, FONT_AVGWIDTH_INDEX, QCavgwidth);
6129 }
6130
6131 attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, spec);
6132 }
6076 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) 6133 if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX]))
6077 { 6134 {
6078 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]); 6135 face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]);
@@ -7360,6 +7417,35 @@ Lisp programs that change the value of this variable should also
7360clear the face cache, see `clear-face-cache'. */); 7417clear the face cache, see `clear-face-cache'. */);
7361 face_near_same_color_threshold = 30000; 7418 face_near_same_color_threshold = 30000;
7362 7419
7420 DEFVAR_LISP ("face-font-lax-matched-attributes",
7421 Vface_font_lax_matched_attributes,
7422 doc: /* Whether to match some face attributes in lax manner when realizing faces.
7423
7424If non-nil, some font-related face attributes will be matched in a lax
7425manner when looking for candidate fonts.
7426If the value is t, the default, the search for fonts will not insist
7427on exact match for 3 font attributes: weight, width, and slant.
7428Instead, it will examine the available fonts with various values of
7429these attributes, and select the font that is the closest possible
7430match. (If an exact match is available, it will still be selected,
7431as that is the closest match.) For example, looking for a semi-bold
7432font might select a bold or a medium-weight font if no semi-bold font
7433matching other attributes can be found. This is especially important
7434when the `default' face specifies unusual values for one or more of
7435these 3 attributes, which other installed fonts don't support.
7436
7437The value can also be a list of font-related face attribute symbols;
7438see `set-face-attribute' for the full list of attributes. Then the
7439corresponding face attributes will be treated as "soft" constraints
7440in the manner described above, instead of the default 3 attributes.
7441
7442If the value is nil, candidate fonts might be rejected if the don't
7443have exactly the same values of attributes as the face requests.
7444
7445This variable exists for debugging of the font-selection process,
7446and we advise not to change it otherwise. */);
7447 Vface_font_lax_matched_attributes = Qt;
7448
7363#ifdef HAVE_WINDOW_SYSTEM 7449#ifdef HAVE_WINDOW_SYSTEM
7364 defsubr (&Sbitmap_spec_p); 7450 defsubr (&Sbitmap_spec_p);
7365 defsubr (&Sx_list_fonts); 7451 defsubr (&Sx_list_fonts);
diff --git a/src/xfns.c b/src/xfns.c
index fa2c0751d90..668f711bdb5 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -43,7 +43,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
43#ifdef USE_XCB 43#ifdef USE_XCB
44#include <xcb/xcb.h> 44#include <xcb/xcb.h>
45#include <xcb/xproto.h> 45#include <xcb/xproto.h>
46#include <xcb/xcb_aux.h>
47#endif 46#endif
48 47
49#include "bitmaps/gray.xbm" 48#include "bitmaps/gray.xbm"
@@ -1368,7 +1367,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1368 XCreateFontCursor is not a request that waits for a reply, 1367 XCreateFontCursor is not a request that waits for a reply,
1369 and as such can return IDs that will not actually be used by 1368 and as such can return IDs that will not actually be used by
1370 the server. */ 1369 the server. */
1371 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f)); 1370 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
1372 1371
1373 /* Free any successfully created cursors. */ 1372 /* Free any successfully created cursors. */
1374 for (i = 0; i < mouse_cursor_max; i++) 1373 for (i = 0; i < mouse_cursor_max; i++)
@@ -2643,12 +2642,18 @@ append_wm_protocols (struct x_display_info *dpyinfo,
2643 if (existing) 2642 if (existing)
2644 XFree (existing); 2643 XFree (existing);
2645 2644
2646 if (!found_wm_ping) 2645 if (!dpyinfo->untrusted)
2647 protos[num_protos++] = dpyinfo->Xatom_net_wm_ping; 2646 {
2647 /* Untrusted clients cannot use these protocols which require
2648 communicating with the window manager. */
2649
2650 if (!found_wm_ping)
2651 protos[num_protos++] = dpyinfo->Xatom_net_wm_ping;
2648#if !defined HAVE_GTK3 && defined HAVE_XSYNC 2652#if !defined HAVE_GTK3 && defined HAVE_XSYNC
2649 if (!found_wm_sync_request && dpyinfo->xsync_supported_p) 2653 if (!found_wm_sync_request && dpyinfo->xsync_supported_p)
2650 protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request; 2654 protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request;
2651#endif 2655#endif
2656 }
2652 2657
2653 if (num_protos) 2658 if (num_protos)
2654 XChangeProperty (dpyinfo->display, 2659 XChangeProperty (dpyinfo->display,
@@ -5723,13 +5728,13 @@ x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
5723 = xcb_get_property (dpyinfo->xcb_connection, 0, 5728 = xcb_get_property (dpyinfo->xcb_connection, 0,
5724 (xcb_window_t) dpyinfo->root_window, 5729 (xcb_window_t) dpyinfo->root_window,
5725 (xcb_atom_t) dpyinfo->Xatom_net_current_desktop, 5730 (xcb_atom_t) dpyinfo->Xatom_net_current_desktop,
5726 XCB_ATOM_CARDINAL, 0, 1); 5731 XA_CARDINAL, 0, 1);
5727 5732
5728 workarea_cookie 5733 workarea_cookie
5729 = xcb_get_property (dpyinfo->xcb_connection, 0, 5734 = xcb_get_property (dpyinfo->xcb_connection, 0,
5730 (xcb_window_t) dpyinfo->root_window, 5735 (xcb_window_t) dpyinfo->root_window,
5731 (xcb_atom_t) dpyinfo->Xatom_net_workarea, 5736 (xcb_atom_t) dpyinfo->Xatom_net_workarea,
5732 XCB_ATOM_CARDINAL, 0, UINT32_MAX); 5737 XA_CARDINAL, 0, UINT32_MAX);
5733 5738
5734 reply = xcb_get_property_reply (dpyinfo->xcb_connection, 5739 reply = xcb_get_property_reply (dpyinfo->xcb_connection,
5735 current_desktop_cookie, &error); 5740 current_desktop_cookie, &error);
@@ -5740,7 +5745,7 @@ x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
5740 else 5745 else
5741 { 5746 {
5742 if (xcb_get_property_value_length (reply) != 4 5747 if (xcb_get_property_value_length (reply) != 4
5743 || reply->type != XCB_ATOM_CARDINAL || reply->format != 32) 5748 || reply->type != XA_CARDINAL || reply->format != 32)
5744 rc = false; 5749 rc = false;
5745 else 5750 else
5746 current_workspace = *(uint32_t *) xcb_get_property_value (reply); 5751 current_workspace = *(uint32_t *) xcb_get_property_value (reply);
@@ -5755,7 +5760,7 @@ x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
5755 free (error), rc = false; 5760 free (error), rc = false;
5756 else 5761 else
5757 { 5762 {
5758 if (rc && reply->type == XCB_ATOM_CARDINAL && reply->format == 32 5763 if (rc && reply->type == XA_CARDINAL && reply->format == 32
5759 && (xcb_get_property_value_length (reply) / sizeof (uint32_t) 5764 && (xcb_get_property_value_length (reply) / sizeof (uint32_t)
5760 >= current_workspace + 4)) 5765 >= current_workspace + 4))
5761 { 5766 {
@@ -7079,8 +7084,8 @@ that mouse buttons are being held down, such as immediately after a
7079 /* Catch errors since interning lots of targets can potentially 7084 /* Catch errors since interning lots of targets can potentially
7080 generate a BadAlloc error. */ 7085 generate a BadAlloc error. */
7081 x_catch_errors (FRAME_X_DISPLAY (f)); 7086 x_catch_errors (FRAME_X_DISPLAY (f));
7082 XInternAtoms (FRAME_X_DISPLAY (f), target_names, 7087 x_intern_atoms (FRAME_DISPLAY_INFO (f), target_names,
7083 ntargets, False, target_atoms); 7088 ntargets, target_atoms);
7084 x_check_errors (FRAME_X_DISPLAY (f), 7089 x_check_errors (FRAME_X_DISPLAY (f),
7085 "Failed to intern target atoms: %s"); 7090 "Failed to intern target atoms: %s");
7086 x_uncatch_errors_after_check (); 7091 x_uncatch_errors_after_check ();
@@ -7377,20 +7382,6 @@ If TERMINAL is omitted or nil, that stands for the selected frame's display. */
7377 return Qnil; 7382 return Qnil;
7378} 7383}
7379 7384
7380/* Wait for responses to all X commands issued so far for frame F. */
7381
7382void
7383x_sync (struct frame *f)
7384{
7385 block_input ();
7386#ifndef USE_XCB
7387 XSync (FRAME_X_DISPLAY (f), False);
7388#else
7389 xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection);
7390#endif
7391 unblock_input ();
7392}
7393
7394 7385
7395/*********************************************************************** 7386/***********************************************************************
7396 Window properties 7387 Window properties
@@ -7484,7 +7475,7 @@ silently ignored. */)
7484 elsize = element_format == 32 ? sizeof (long) : element_format >> 3; 7475 elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
7485 data = xnmalloc (nelements, elsize); 7476 data = xnmalloc (nelements, elsize);
7486 7477
7487 x_fill_property_data (FRAME_X_DISPLAY (f), value, data, nelements, 7478 x_fill_property_data (FRAME_DISPLAY_INFO (f), value, data, nelements,
7488 element_format); 7479 element_format);
7489 } 7480 }
7490 else 7481 else
@@ -8455,10 +8446,10 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx,
8455 int min_x, min_y, max_x, max_y = -1; 8446 int min_x, min_y, max_x, max_y = -1;
8456 8447
8457 /* User-specified position? */ 8448 /* User-specified position? */
8458 left = Fcdr (Fassq (Qleft, parms)); 8449 left = CDR (Fassq (Qleft, parms));
8459 top = Fcdr (Fassq (Qtop, parms)); 8450 top = CDR (Fassq (Qtop, parms));
8460 right = Fcdr (Fassq (Qright, parms)); 8451 right = CDR (Fassq (Qright, parms));
8461 bottom = Fcdr (Fassq (Qbottom, parms)); 8452 bottom = CDR (Fassq (Qbottom, parms));
8462 8453
8463 /* Move the tooltip window where the mouse pointer is. Resize and 8454 /* Move the tooltip window where the mouse pointer is. Resize and
8464 show it. */ 8455 show it. */
@@ -8824,14 +8815,14 @@ Text larger than the specified size is clipped. */)
8824 for (tail = parms; CONSP (tail); tail = XCDR (tail)) 8815 for (tail = parms; CONSP (tail); tail = XCDR (tail))
8825 { 8816 {
8826 elt = XCAR (tail); 8817 elt = XCAR (tail);
8827 parm = Fcar (elt); 8818 parm = CAR (elt);
8828 /* The left, top, right and bottom parameters are handled 8819 /* The left, top, right and bottom parameters are handled
8829 by compute_tip_xy so they can be ignored here. */ 8820 by compute_tip_xy so they can be ignored here. */
8830 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) 8821 if (!EQ (parm, Qleft) && !EQ (parm, Qtop)
8831 && !EQ (parm, Qright) && !EQ (parm, Qbottom)) 8822 && !EQ (parm, Qright) && !EQ (parm, Qbottom))
8832 { 8823 {
8833 last = Fassq (parm, tip_last_parms); 8824 last = Fassq (parm, tip_last_parms);
8834 if (NILP (Fequal (Fcdr (elt), Fcdr (last)))) 8825 if (NILP (Fequal (CDR (elt), CDR (last))))
8835 { 8826 {
8836 /* We lost, delete the old tooltip. */ 8827 /* We lost, delete the old tooltip. */
8837 delete = true; 8828 delete = true;
@@ -8852,9 +8843,9 @@ Text larger than the specified size is clipped. */)
8852 for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail)) 8843 for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail))
8853 { 8844 {
8854 elt = XCAR (tail); 8845 elt = XCAR (tail);
8855 parm = Fcar (elt); 8846 parm = CAR (elt);
8856 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright) 8847 if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright)
8857 && !EQ (parm, Qbottom) && !NILP (Fcdr (elt))) 8848 && !EQ (parm, Qbottom) && !NILP (CDR (elt)))
8858 { 8849 {
8859 /* We lost, delete the old tooltip. */ 8850 /* We lost, delete the old tooltip. */
8860 delete = true; 8851 delete = true;
@@ -8975,8 +8966,8 @@ Text larger than the specified size is clipped. */)
8975 make_fixnum (w->pixel_height), Qnil, 8966 make_fixnum (w->pixel_height), Qnil,
8976 Qnil); 8967 Qnil);
8977 /* Add the frame's internal border to calculated size. */ 8968 /* Add the frame's internal border to calculated size. */
8978 width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); 8969 width = XFIXNUM (CAR (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
8979 height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); 8970 height = XFIXNUM (CDR (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
8980 8971
8981 /* Calculate position of tooltip frame. */ 8972 /* Calculate position of tooltip frame. */
8982 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y); 8973 compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y);
diff --git a/src/xftfont.c b/src/xftfont.c
index 6043ef9f94f..b9686db2a73 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -628,6 +628,12 @@ xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
628static int 628static int
629xftfont_end_for_frame (struct frame *f) 629xftfont_end_for_frame (struct frame *f)
630{ 630{
631 /* XftDrawDestroy tries to access dpyinfo->display, which could've
632 been destroyed by now, causing Emacs to crash. The alternative
633 is to leak the XftDraw, but that's better than a crash. */
634 if (!FRAME_X_DISPLAY (f))
635 return 0;
636
631 block_input (); 637 block_input ();
632 XftDraw *xft_draw; 638 XftDraw *xft_draw;
633 639
diff --git a/src/xselect.c b/src/xselect.c
index a381fa23522..05548be311f 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -16,7 +16,6 @@ GNU General Public License for more details.
16You should have received a copy of the GNU General Public License 16You should have received a copy of the GNU General Public License
17along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ 17along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
18 18
19
20/* Rewritten by jwz */ 19/* Rewritten by jwz */
21 20
22#include <config.h> 21#include <config.h>
@@ -44,7 +43,7 @@ struct prop_location;
44struct selection_data; 43struct selection_data;
45 44
46static void x_decline_selection_request (struct selection_input_event *); 45static void x_decline_selection_request (struct selection_input_event *);
47static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom, bool, 46static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom,
48 struct x_display_info *, bool); 47 struct x_display_info *, bool);
49static bool waiting_for_other_props_on_window (Display *, Window); 48static bool waiting_for_other_props_on_window (Display *, Window);
50static struct prop_location *expect_property_change (Display *, Window, 49static struct prop_location *expect_property_change (Display *, Window,
@@ -77,18 +76,20 @@ static void x_send_client_event (Lisp_Object, Lisp_Object, Lisp_Object,
77#define TRACE0(fmt) (void) 0 76#define TRACE0(fmt) (void) 0
78#define TRACE1(fmt, a0) (void) 0 77#define TRACE1(fmt, a0) (void) 0
79#define TRACE2(fmt, a0, a1) (void) 0 78#define TRACE2(fmt, a0, a1) (void) 0
79#define TRACE3(fmt, a0, a1, a2) (void) 0
80#endif 80#endif
81 81
82/* Bytes needed to represent 'long' data. This is as per libX11; it 82/* Bytes needed to represent 'long' data. This is as per libX11; it
83 is not necessarily sizeof (long). */ 83 is not necessarily sizeof (long). */
84#define X_LONG_SIZE 4 84#define X_LONG_SIZE 4
85 85
86/* If this is a smaller number than the max-request-size of the display, 86/* If this is a smaller number than the max-request-size of the
87 emacs will use INCR selection transfer when the selection is larger 87 display, Emacs will use INCR selection transfer when the selection
88 than this. The max-request-size is usually around 64k, so if you want 88 is larger than this. The max-request-size is usually around 64k,
89 emacs to use incremental selection transfers when the selection is 89 so if you want emacs to use incremental selection transfers when
90 smaller than that, set this. I added this mostly for debugging the 90 the selection is smaller than that, set this. I added this mostly
91 incremental transfer stuff, but it might improve server performance. 91 for debugging the incremental transfer stuff, but it might improve
92 server performance.
92 93
93 This value cannot exceed INT_MAX / max (X_LONG_SIZE, sizeof (long)) 94 This value cannot exceed INT_MAX / max (X_LONG_SIZE, sizeof (long))
94 because it is multiplied by X_LONG_SIZE and by sizeof (long) in 95 because it is multiplied by X_LONG_SIZE and by sizeof (long) in
@@ -101,7 +102,9 @@ static void x_send_client_event (Lisp_Object, Lisp_Object, Lisp_Object,
101static int 102static int
102selection_quantum (Display *display) 103selection_quantum (Display *display)
103{ 104{
104 long mrs = XExtendedMaxRequestSize (display); 105 long mrs;
106
107 mrs = XExtendedMaxRequestSize (display);
105 108
106 if (!mrs) 109 if (!mrs)
107 mrs = XMaxRequestSize (display); 110 mrs = XMaxRequestSize (display);
@@ -281,10 +284,8 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
281 timestamp = dpyinfo->last_user_time; 284 timestamp = dpyinfo->last_user_time;
282 285
283 block_input (); 286 block_input ();
284 x_catch_errors (display); 287 XSetSelectionOwner (display, selection_atom, selecting_window,
285 XSetSelectionOwner (display, selection_atom, selecting_window, timestamp); 288 timestamp);
286 x_check_errors (display, "Can't set selection: %s");
287 x_uncatch_errors_after_check ();
288 unblock_input (); 289 unblock_input ();
289 290
290 /* Now update the local cache */ 291 /* Now update the local cache */
@@ -308,7 +309,7 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
308 /* We know it's not the CAR, so it's easy. */ 309 /* We know it's not the CAR, so it's easy. */
309 Lisp_Object rest = dpyinfo->terminal->Vselection_alist; 310 Lisp_Object rest = dpyinfo->terminal->Vselection_alist;
310 for (; CONSP (rest); rest = XCDR (rest)) 311 for (; CONSP (rest); rest = XCDR (rest))
311 if (EQ (prev_value, Fcar (XCDR (rest)))) 312 if (EQ (prev_value, CAR (XCDR (rest))))
312 { 313 {
313 XSETCDR (rest, XCDR (XCDR (rest))); 314 XSETCDR (rest, XCDR (XCDR (rest)));
314 break; 315 break;
@@ -369,7 +370,7 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
369 specbind (Qinhibit_quit, Qt); 370 specbind (Qinhibit_quit, Qt);
370 371
371 CHECK_SYMBOL (target_type); 372 CHECK_SYMBOL (target_type);
372 handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); 373 handler_fn = CDR (Fassq (target_type, Vselection_converter_alist));
373 374
374 if (CONSP (handler_fn)) 375 if (CONSP (handler_fn))
375 handler_fn = XCDR (handler_fn); 376 handler_fn = XCDR (handler_fn);
@@ -459,7 +460,7 @@ x_decline_selection_request (struct selection_input_event *event)
459 /* The reason for the error may be that the receiver has 460 /* The reason for the error may be that the receiver has
460 died in the meantime. Handle that case. */ 461 died in the meantime. Handle that case. */
461 block_input (); 462 block_input ();
462 x_ignore_errors_for_next_request (dpyinfo); 463 x_ignore_errors_for_next_request (dpyinfo, 0);
463 XSendEvent (dpyinfo->display, reply->requestor, 464 XSendEvent (dpyinfo->display, reply->requestor,
464 False, 0, &reply_base); 465 False, 0, &reply_base);
465 x_stop_ignoring_errors (dpyinfo); 466 x_stop_ignoring_errors (dpyinfo);
@@ -472,19 +473,65 @@ x_decline_selection_request (struct selection_input_event *event)
472 473
473struct selection_data 474struct selection_data
474{ 475{
476 /* Pointer to the selection data. */
475 unsigned char *data; 477 unsigned char *data;
478
479 /* A Lisp_Object containing the selection data. This is either
480 Qnil, or `data' is NULL. If non-nil, then this must be a string
481 whose contents will be written out verbatim. */
482 Lisp_Object string;
483
484 /* The size, in number of items, of the selection data.
485 The value is meaningless if string is non-nil. */
476 ptrdiff_t size; 486 ptrdiff_t size;
487
488 /* The format of the selection data. */
477 int format; 489 int format;
490
491 /* The type of the selection data. */
478 Atom type; 492 Atom type;
479 bool nofree; 493
494 /* The property describing the selection data. */
480 Atom property; 495 Atom property;
481 /* This can be set to non-NULL during x_reply_selection_request, if 496
482 the selection is waiting for an INCR transfer to complete. Don't 497 /* The next piece of selection data in the current selection request
483 free these; that's done by unexpect_property_change. */ 498 stack frame. This can be NULL. */
484 struct prop_location *wait_object;
485 struct selection_data *next; 499 struct selection_data *next;
486}; 500};
487 501
502/* Structure representing a single outstanding selection request (or
503 subrequest if MULTIPLE is being used.) */
504
505struct transfer
506{
507 /* The requestor of this transfer. */
508 Window requestor;
509
510 /* The current offset in items into the selection data, and the
511 number of items to send with each ChangeProperty request. */
512 size_t offset, items_per_request;
513
514 /* The display info associated with the transfer. */
515 struct x_display_info *dpyinfo;
516
517 /* The converted selection data. */
518 struct selection_data data;
519
520 /* The next and last selection transfers on this list. */
521 struct transfer *next, *last;
522
523 /* The atimer for the timeout. */
524 struct atimer *timeout;
525
526 /* The selection serial. */
527 unsigned int serial;
528
529 /* Flags. */
530 int flags;
531};
532
533#define SELECTED_EVENTS 1
534
488struct x_selection_request 535struct x_selection_request
489{ 536{
490 /* The last element in this stack. */ 537 /* The last element in this stack. */
@@ -499,8 +546,8 @@ struct x_selection_request
499 /* Linked list of the above (in support of MULTIPLE targets). */ 546 /* Linked list of the above (in support of MULTIPLE targets). */
500 struct selection_data *converted_selections; 547 struct selection_data *converted_selections;
501 548
502 /* "Data" to send a requestor for a failed MULTIPLE subtarget. */ 549 /* The serial used to handle X errors. */
503 Atom conversion_fail_tag; 550 unsigned int serial;
504 551
505 /* Whether or not conversion was successful. */ 552 /* Whether or not conversion was successful. */
506 bool converted; 553 bool converted;
@@ -511,6 +558,50 @@ struct x_selection_request
511 558
512struct x_selection_request *selection_request_stack; 559struct x_selection_request *selection_request_stack;
513 560
561/* List of all outstanding selection transfers which are currently
562 being processed. */
563
564struct transfer outstanding_transfers;
565
566/* A counter for selection serials. */
567
568static unsigned int selection_serial;
569
570
571
572struct prop_location
573{
574 int identifier;
575 Display *display;
576 Window window;
577 Atom property;
578 int desired_state;
579 bool arrived;
580 struct prop_location *next;
581};
582
583static int prop_location_identifier;
584
585static Lisp_Object property_change_reply;
586
587static struct prop_location *property_change_reply_object;
588
589static struct prop_location *property_change_wait_list;
590
591static void
592set_property_change_object (struct prop_location *location)
593{
594 /* Input must be blocked so we don't get the event before we set
595 these. */
596 if (! input_blocked_p ())
597 emacs_abort ();
598
599 XSETCAR (property_change_reply, Qnil);
600 property_change_reply_object = location;
601}
602
603
604
514static void 605static void
515x_push_current_selection_request (struct selection_input_event *se, 606x_push_current_selection_request (struct selection_input_event *se,
516 struct x_display_info *dpyinfo) 607 struct x_display_info *dpyinfo)
@@ -523,7 +614,6 @@ x_push_current_selection_request (struct selection_input_event *se,
523 frame->request = se; 614 frame->request = se;
524 frame->dpyinfo = dpyinfo; 615 frame->dpyinfo = dpyinfo;
525 frame->converted_selections = NULL; 616 frame->converted_selections = NULL;
526 frame->conversion_fail_tag = None;
527 617
528 selection_request_stack = frame; 618 selection_request_stack = frame;
529} 619}
@@ -554,7 +644,7 @@ x_selection_request_lisp_error (void)
554 for (cs = frame->converted_selections; cs; cs = next) 644 for (cs = frame->converted_selections; cs; cs = next)
555 { 645 {
556 next = cs->next; 646 next = cs->next;
557 if (! cs->nofree && cs->data) 647 if (cs->data)
558 xfree (cs->data); 648 xfree (cs->data);
559 xfree (cs); 649 xfree (cs);
560 } 650 }
@@ -564,250 +654,450 @@ x_selection_request_lisp_error (void)
564 x_decline_selection_request (frame->request); 654 x_decline_selection_request (frame->request);
565} 655}
566 656
567static void 657
568x_catch_errors_unwind (void) 658
659static size_t
660c_size_for_format (int format)
569{ 661{
570 block_input (); 662 switch (format)
571 x_uncatch_errors (); 663 {
572 unblock_input (); 664 case 8:
665 return sizeof (char);
666
667 case 16:
668 return sizeof (short);
669
670 case 32:
671 return sizeof (long);
672 }
673
674 emacs_abort ();
573} 675}
574
575 676
576/* This stuff is so that INCR selections are reentrant (that is, so we can 677static size_t
577 be servicing multiple INCR selection requests simultaneously.) I haven't 678x_size_for_format (int format)
578 actually tested that yet. */ 679{
680 switch (format)
681 {
682 case 8:
683 return 1;
684
685 case 16:
686 return 2;
579 687
580/* Keep a list of the property changes that are awaited. */ 688 case 32:
689 return 4;
690 }
581 691
582struct prop_location 692 emacs_abort ();
693}
694
695/* Return a pointer to the remaining part of the selection data, given
696 a pointer to a struct selection_data and an offset in items. Place
697 the number of items remaining in REMAINING. Garbage collection
698 must not happen, or the returned pointer becomes invalid. */
699
700static unsigned char *
701selection_data_for_offset (struct selection_data *data,
702 long offset, size_t *remaining)
583{ 703{
584 int identifier; 704 unsigned char *base;
585 Display *display; 705 size_t size;
586 Window window;
587 Atom property;
588 int desired_state;
589 bool arrived;
590 struct prop_location *next;
591};
592 706
593static int prop_location_identifier; 707 if (!NILP (data->string))
708 {
709 base = SDATA (data->string);
710 size = SBYTES (data->string);
711 }
712 else
713 {
714 base = data->data;
715 size = data->size;
716 }
594 717
595static Lisp_Object property_change_reply; 718 if (offset >= size)
719 {
720 *remaining = 0;
721 return NULL;
722 }
596 723
597static struct prop_location *property_change_reply_object; 724 base += (offset * c_size_for_format (data->format));
725 *remaining = size - offset;
726 return base;
727}
598 728
599static struct prop_location *property_change_wait_list; 729/* Return the size, in bytes transferred to the X server, of
730 data->size items of selection data in data->format-bit
731 quantities. */
600 732
601static void 733static size_t
602set_property_change_object (struct prop_location *location) 734selection_data_size (struct selection_data *data)
603{ 735{
604 /* Input must be blocked so we don't get the event before we set these. */ 736 size_t scratch;
605 if (! input_blocked_p ()) 737
606 emacs_abort (); 738 if (!NILP (data->string))
607 XSETCAR (property_change_reply, Qnil); 739 return SBYTES (data->string);
608 property_change_reply_object = location; 740
741 switch (data->format)
742 {
743 case 8:
744 return (size_t) data->size;
745
746 case 16:
747 if (INT_MULTIPLY_WRAPV (data->size, 2, &scratch))
748 return SIZE_MAX;
749
750 return scratch;
751
752 case 32:
753 if (INT_MULTIPLY_WRAPV (data->size, 4, &scratch))
754 return SIZE_MAX;
755
756 return scratch;
757 }
758
759 /* The specified format is invalid. */
760 emacs_abort ();
609} 761}
610 762
611 763/* Return whether or not another outstanding selection transfer is
612/* Send the reply to a selection request event EVENT. */ 764 still selecting for events on the specified requestor window. */
613 765
614#ifdef TRACE_SELECTION 766static bool
615static int x_reply_selection_request_cnt; 767transfer_selecting_event (struct x_display_info *dpyinfo,
616#endif /* TRACE_SELECTION */ 768 Window requestor)
769{
770 struct transfer *next;
771
772 next = outstanding_transfers.next;
773 for (; next != &outstanding_transfers; next = next->next)
774 {
775 if (next->requestor == requestor
776 && next->dpyinfo == dpyinfo)
777 return true;
778 }
779
780 return false;
781}
782
783/* Cancel the specified selection transfer. When called by
784 `start_transfer', the transfer may be partially formed. */
617 785
618static void 786static void
619x_reply_selection_request (struct selection_input_event *event, 787x_cancel_selection_transfer (struct transfer *transfer)
620 struct x_display_info *dpyinfo)
621{ 788{
622 XEvent reply_base; 789 xfree (transfer->data.data);
623 XSelectionEvent *reply = &(reply_base.xselection);
624 Display *display = SELECTION_EVENT_DISPLAY (event);
625 Window window = SELECTION_EVENT_REQUESTOR (event);
626 ptrdiff_t bytes_remaining;
627 int max_bytes = selection_quantum (display);
628 specpdl_ref count = SPECPDL_INDEX ();
629 struct selection_data *cs;
630 struct x_selection_request *frame;
631 790
632 frame = selection_request_stack; 791 if (transfer->next)
792 {
793 transfer->next->last = transfer->last;
794 transfer->last->next = transfer->next;
795 }
633 796
634 reply->type = SelectionNotify; 797 if (transfer->flags & SELECTED_EVENTS
635 reply->display = display; 798 && !transfer_selecting_event (transfer->dpyinfo,
636 reply->requestor = window; 799 transfer->requestor)
637 reply->selection = SELECTION_EVENT_SELECTION (event); 800 /* This can be called from x_delete_display. */
638 reply->time = SELECTION_EVENT_TIME (event); 801 && transfer->dpyinfo->display)
639 reply->target = SELECTION_EVENT_TARGET (event); 802 {
640 reply->property = SELECTION_EVENT_PROPERTY (event); 803 /* Ignore errors generated by the change window request in case
641 if (reply->property == None) 804 the window has gone away. */
642 reply->property = reply->target; 805 block_input ();
806 x_ignore_errors_for_next_request (transfer->dpyinfo, 0);
807 XSelectInput (transfer->dpyinfo->display,
808 transfer->requestor, NoEventMask);
809 x_stop_ignoring_errors (transfer->dpyinfo);
810 unblock_input ();
811 }
643 812
644 block_input (); 813 cancel_atimer (transfer->timeout);
645 /* The protected block contains wait_for_property_change, which can 814 xfree (transfer);
646 run random lisp code (process handlers) or signal. Therefore, we 815}
647 put the x_uncatch_errors call in an unwind. */
648 record_unwind_protect_void (x_catch_errors_unwind);
649 x_catch_errors (display);
650 816
651 /* Loop over converted selections, storing them in the requested 817static void
652 properties. If data is large, only store the first N bytes 818x_selection_transfer_timeout (struct atimer *atimer)
653 (section 2.7.2 of ICCCM). Note that we store the data for a 819{
654 MULTIPLE request in the opposite order; the ICCM says only that 820 struct transfer *transfer;
655 the conversion itself must be done in the same order. */ 821
656 for (cs = frame->converted_selections; cs; cs = cs->next) 822 transfer = atimer->client_data;
823 x_cancel_selection_transfer (transfer);
824}
825
826/* Start a selection transfer to write the specified selection data to
827 its requestor. If the data is small enough, write it to the
828 requestor window and return. Otherwise, start INCR transfer and
829 begin listening for PropertyNotify events on the requestor. */
830
831static void
832x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
833 struct selection_data *data)
834{
835 struct transfer *transfer;
836 intmax_t timeout;
837 intmax_t secs;
838 int nsecs;
839 size_t remaining, max_size;
840 unsigned char *xdata;
841 unsigned long data_size;
842
843 timeout = max (0, x_selection_timeout);
844 secs = timeout / 1000;
845 nsecs = (timeout % 1000) * 1000000;
846
847 transfer = xzalloc (sizeof *transfer);
848 transfer->requestor = requestor;
849 transfer->dpyinfo = dpyinfo;
850
851 transfer->timeout = start_atimer (ATIMER_RELATIVE,
852 make_timespec (secs, nsecs),
853 x_selection_transfer_timeout,
854 transfer);
855
856 /* Note that DATA is copied into transfer. DATA->data is then set
857 to NULL, giving the struct transfer ownership over the selection
858 data. */
859
860 transfer->data = *data;
861 data->data = NULL;
862
863 /* Finally, transfer now holds a reference to data->string, if it is
864 present. GC cannot be allowed to happen until this function
865 returns. */
866 data->string = Qnil;
867
868 /* Now, try to write the selection data. If it is bigger than
869 selection_quantum (dpyinfo->display), start incremental transfer
870 and link the transfer onto the list of pending selections.
871 Otherwise, write the transfer at once. */
872
873 max_size = selection_quantum (dpyinfo->display);
874
875 TRACE3 (" x_start_selection_transfer: transferring to 0x%lx. "
876 "transfer consists of %zu bytes, quantum being %zu",
877 requestor, selection_data_size (&transfer->data),
878 max_size);
879
880 if (selection_data_size (&transfer->data) > max_size)
657 { 881 {
658 if (cs->property == None) 882 /* Begin incremental selection transfer. First, calculate how
659 continue; 883 many elements it is ok to write for every ChangeProperty
884 request. */
885 transfer->items_per_request
886 = (max_size / x_size_for_format (transfer->data.format));
887 TRACE1 (" x_start_selection_transfer: starting incremental"
888 " selection transfer, with %zu items per request",
889 transfer->items_per_request);
890
891 /* Next, link the transfer onto the list of pending selection
892 transfers. */
893 transfer->next = outstanding_transfers.next;
894 transfer->last = &outstanding_transfers;
895 transfer->next->last = transfer;
896 transfer->last->next = transfer;
897
898 /* Find a valid (non-zero) serial for the selection transfer.
899 Any asynchronously trapped errors will then cause the
900 selection transfer to be cancelled. */
901 transfer->serial = (++selection_serial
902 ? selection_serial
903 : ++selection_serial);
904
905 /* Now, write the INCR property to begin incremental selection
906 transfer. offset is currently 0. */
907
908 data_size = selection_data_size (&transfer->data);
909
910 /* Set SELECTED_EVENTS before the actual XSelectInput
911 request. */
912 transfer->flags |= SELECTED_EVENTS;
913
914 x_ignore_errors_for_next_request (dpyinfo, transfer->serial);
915 XChangeProperty (dpyinfo->display, requestor,
916 transfer->data.property,
917 dpyinfo->Xatom_INCR, 32, PropModeReplace,
918 (unsigned char *) &data_size, 1);
919
920 /* This assumes that Emacs is not selecting for any other events
921 from the requestor!
922
923 If the holder of some manager selections (i.e. the settings
924 manager) asks Emacs for selection data, things will subtly go
925 wrong. */
926 XSelectInput (dpyinfo->display, requestor, PropertyChangeMask);
927 x_stop_ignoring_errors (dpyinfo);
928 }
929 else
930 {
931 /* Write the property data now. */
932 xdata = selection_data_for_offset (&transfer->data,
933 0, &remaining);
934 eassert (remaining <= INT_MAX);
935
936 TRACE1 (" x_start_selection_transfer: writing"
937 " %zu elements directly to requestor window",
938 remaining);
939
940 x_ignore_errors_for_next_request (dpyinfo, 0);
941 XChangeProperty (dpyinfo->display, requestor,
942 transfer->data.property,
943 transfer->data.type,
944 transfer->data.format,
945 PropModeReplace, xdata, remaining);
946 x_stop_ignoring_errors (dpyinfo);
947
948 /* Next, get rid of the transfer. */
949 x_cancel_selection_transfer (transfer);
950 }
951}
660 952
661 bytes_remaining = cs->size; 953/* Write out the next piece of data that is part of the specified
662 bytes_remaining *= cs->format >> 3; 954 selection transfer. If no more data remains to be written, write
663 if (bytes_remaining <= max_bytes) 955 the EOF property and complete the transfer. */
664 { 956
665 /* Send all the data at once, with minimal handshaking. */ 957static void
666 TRACE1 ("Sending all %"pD"d bytes", bytes_remaining); 958x_continue_selection_transfer (struct transfer *transfer)
667 XChangeProperty (display, window, cs->property, 959{
668 cs->type, cs->format, PropModeReplace, 960 size_t remaining;
669 cs->data, cs->size); 961 unsigned char *xdata;
670 } 962
671 else 963 xdata = selection_data_for_offset (&transfer->data,
672 { 964 transfer->offset,
673 /* Send an INCR tag to initiate incremental transfer. */ 965 &remaining);
674 long value[1]; 966 remaining = min (remaining, transfer->items_per_request);
675 967
676 TRACE2 ("Start sending %"pD"d bytes incrementally (%s)", 968 if (!remaining)
677 bytes_remaining, XGetAtomName (display, cs->property)); 969 {
678 cs->wait_object 970 /* The transfer is finished. Write zero-length property data to
679 = expect_property_change (display, window, cs->property, 971 signal EOF and remove the transfer. */
680 PropertyDelete); 972 TRACE0 (" x_continue_selection_transfer: writing 0 items to"
681 973 " indicate EOF");
682 /* XChangeProperty expects an array of long even if long is 974 x_ignore_errors_for_next_request (transfer->dpyinfo, 0);
683 more than 32 bits. */ 975 XChangeProperty (transfer->dpyinfo->display,
684 value[0] = min (bytes_remaining, X_LONG_MAX); 976 transfer->requestor,
685 XChangeProperty (display, window, cs->property, 977 transfer->data.property,
686 dpyinfo->Xatom_INCR, 32, PropModeReplace, 978 transfer->data.type,
687 (unsigned char *) value, 1); 979 transfer->data.format,
688 XSelectInput (display, window, PropertyChangeMask); 980 PropModeReplace,
689 } 981 NULL, 0);
982 x_stop_ignoring_errors (transfer->dpyinfo);
983 TRACE0 (" x_continue_selection_transfer: done sending incrementally");
984
985 x_cancel_selection_transfer (transfer);
986 }
987 else
988 {
989 TRACE2 (" x_continue_selection_transfer: writing %zu items"
990 "; current offset is %zu", remaining, transfer->offset);
991 eassert (remaining <= INT_MAX);
992
993 transfer->offset += remaining;
994
995 x_ignore_errors_for_next_request (transfer->dpyinfo,
996 transfer->serial);
997 XChangeProperty (transfer->dpyinfo->display,
998 transfer->requestor,
999 transfer->data.property,
1000 transfer->data.type,
1001 transfer->data.format,
1002 PropModeReplace, xdata,
1003 remaining);
1004 x_stop_ignoring_errors (transfer->dpyinfo);
690 } 1005 }
1006}
691 1007
692 /* Now issue the SelectionNotify event. */ 1008void
693 XSendEvent (display, window, False, 0, &reply_base); 1009x_remove_selection_transfers (struct x_display_info *dpyinfo)
694 XFlush (display); 1010{
1011 struct transfer *next, *last;
695 1012
696#ifdef TRACE_SELECTION 1013 next = outstanding_transfers.next;
697 { 1014 while (next != &outstanding_transfers)
698 char *sel = XGetAtomName (display, reply->selection); 1015 {
699 char *tgt = XGetAtomName (display, reply->target); 1016 last = next;
700 TRACE3 ("Sent SelectionNotify: %s, target %s (%d)", 1017 next = next->next;
701 sel, tgt, ++x_reply_selection_request_cnt);
702 if (sel) XFree (sel);
703 if (tgt) XFree (tgt);
704 }
705#endif /* TRACE_SELECTION */
706 1018
707 /* Finish sending the rest of each of the INCR values. This should 1019 if (last->dpyinfo == dpyinfo)
708 be improved; there's a chance of deadlock if more than one 1020 x_cancel_selection_transfer (last);
709 subtarget in a MULTIPLE selection requires an INCR transfer, and 1021 }
710 the requestor and Emacs loop waiting on different transfers. */ 1022}
711 for (cs = frame->converted_selections; cs; cs = cs->next)
712 if (cs->wait_object)
713 {
714 int format_bytes = cs->format / 8;
715 bool had_errors_p = x_had_errors_p (display);
716 1023
717 /* Must set this inside block_input (). unblock_input may read 1024/* Handle an X error generated trying to write to a window. SERIAL
718 events and setting property_change_reply in 1025 identifies the outstanding incremental selection transfer, which is
719 wait_for_property_change is then too late. */ 1026 immediately removed. */
720 set_property_change_object (cs->wait_object);
721 unblock_input ();
722 1027
723 bytes_remaining = cs->size; 1028void
724 bytes_remaining *= format_bytes; 1029x_handle_selection_error (unsigned int serial, XErrorEvent *error)
1030{
1031 struct transfer *next, *last;
725 1032
726 /* Wait for the requestor to ack by deleting the property. 1033 if (error->error_code != BadWindow)
727 This can run Lisp code (process handlers) or signal. */ 1034 /* The error was not caused by the window going away. As such,
728 if (! had_errors_p) 1035 Emacs must deselect for PropertyChangeMask from the requestor
729 { 1036 window, which isn't safe here. Return and wait for the timeout
730 TRACE1 ("Waiting for ACK (deletion of %s)", 1037 to run. */
731 XGetAtomName (display, cs->property)); 1038 return;
732 wait_for_property_change (cs->wait_object);
733 }
734 else
735 unexpect_property_change (cs->wait_object);
736 1039
737 while (bytes_remaining) 1040 next = outstanding_transfers.next;
738 { 1041 while (next != &outstanding_transfers)
739 int i = ((bytes_remaining < max_bytes) 1042 {
740 ? bytes_remaining 1043 last = next;
741 : max_bytes) / format_bytes; 1044 next = next->next;
742 block_input ();
743
744 cs->wait_object
745 = expect_property_change (display, window, cs->property,
746 PropertyDelete);
747
748 TRACE1 ("Sending increment of %d elements", i);
749 TRACE1 ("Set %s to increment data",
750 XGetAtomName (display, cs->property));
751
752 /* Append the next chunk of data to the property. */
753 XChangeProperty (display, window, cs->property,
754 cs->type, cs->format, PropModeAppend,
755 cs->data, i);
756 bytes_remaining -= i * format_bytes;
757 cs->data += i * ((cs->format == 32) ? sizeof (long)
758 : format_bytes);
759 XFlush (display);
760 had_errors_p = x_had_errors_p (display);
761 /* See comment above about property_change_reply. */
762 set_property_change_object (cs->wait_object);
763 unblock_input ();
764
765 if (had_errors_p) break;
766
767 /* Wait for the requestor to ack this chunk by deleting
768 the property. This can run Lisp code or signal. */
769 TRACE1 ("Waiting for increment ACK (deletion of %s)",
770 XGetAtomName (display, cs->property));
771 wait_for_property_change (cs->wait_object);
772 }
773 1045
774 /* Now write a zero-length chunk to the property to tell the 1046 if (last->serial == serial)
775 requestor that we're done. */ 1047 {
776 block_input (); 1048 /* Clear SELECTED_EVENTS, so x_cancel_selection_transfer
777 if (! waiting_for_other_props_on_window (display, window)) 1049 will not make X requests. That is unsafe inside an error
778 XSelectInput (display, window, 0); 1050 handler, and unnecessary because the window has already
779 1051 gone. */
780 TRACE1 ("Set %s to a 0-length chunk to indicate EOF", 1052 last->flags &= ~SELECTED_EVENTS;
781 XGetAtomName (display, cs->property)); 1053 x_cancel_selection_transfer (last);
782 XChangeProperty (display, window, cs->property, 1054 }
783 cs->type, cs->format, PropModeReplace, 1055 }
784 cs->data, 0); 1056}
785 TRACE0 ("Done sending incrementally");
786 }
787 1057
788 /* rms, 2003-01-03: I think I have fixed this bug. */ 1058/* Send the reply to a selection request event EVENT. */
789 /* The window we're communicating with may have been deleted 1059
790 in the meantime (that's a real situation from a bug report). 1060static void
791 In this case, there may be events in the event queue still 1061x_reply_selection_request (struct selection_input_event *event,
792 referring to the deleted window, and we'll get a BadWindow error 1062 struct x_display_info *dpyinfo)
793 in XTread_socket when processing the events. I don't have 1063{
794 an idea how to fix that. gerd, 2001-01-98. */ 1064 XEvent message;
795 /* 2004-09-10: XSync and UNBLOCK so that possible protocol errors are 1065 struct selection_data *cs;
796 delivered before uncatch errors. */ 1066 struct x_selection_request *frame;
797 XSync (display, False);
798 unblock_input ();
799 1067
800 /* GTK queues events in addition to the queue in Xlib. So we
801 UNBLOCK to enter the event loop and get possible errors delivered,
802 and then BLOCK again because x_uncatch_errors requires it. */
803 block_input (); 1068 block_input ();
804 /* This calls x_uncatch_errors. */ 1069 frame = selection_request_stack;
805 unbind_to (count, Qnil); 1070
1071 message.xselection.type = SelectionNotify;
1072 message.xselection.display = dpyinfo->display;
1073 message.xselection.requestor = SELECTION_EVENT_REQUESTOR (event);
1074 message.xselection.selection = SELECTION_EVENT_SELECTION (event);
1075 message.xselection.time = SELECTION_EVENT_TIME (event);
1076 message.xselection.target = SELECTION_EVENT_TARGET (event);
1077 message.xselection.property = SELECTION_EVENT_PROPERTY (event);
1078
1079 if (message.xselection.property == None)
1080 message.xselection.property = message.xselection.target;
1081
1082 /* For each of the converted selections, start a write transfer from
1083 Emacs to the requestor. */
1084 for (cs = frame->converted_selections; cs; cs = cs->next)
1085 x_start_selection_transfer (dpyinfo,
1086 SELECTION_EVENT_REQUESTOR (event),
1087 cs);
1088
1089
1090 /* Send the SelectionNotify event to the requestor, telling it that
1091 the property data has arrived. */
1092 x_ignore_errors_for_next_request (dpyinfo, 0);
1093 XSendEvent (dpyinfo->display, SELECTION_EVENT_REQUESTOR (event),
1094 False, NoEventMask, &message);
1095 x_stop_ignoring_errors (dpyinfo);
806 unblock_input (); 1096 unblock_input ();
807} 1097}
808 1098
809/* Handle a SelectionRequest event EVENT. 1099/* Handle a SelectionRequest event EVENT. This is called from
810 This is called from keyboard.c when such an event is found in the queue. */ 1100 keyboard.c when such an event is found in the queue. */
811 1101
812static void 1102static void
813x_handle_selection_request (struct selection_input_event *event) 1103x_handle_selection_request (struct selection_input_event *event)
@@ -892,7 +1182,9 @@ x_handle_selection_request (struct selection_input_event *event)
892 ptrdiff_t j, nselections; 1182 ptrdiff_t j, nselections;
893 struct selection_data cs; 1183 struct selection_data cs;
894 1184
895 if (property == None) goto DONE; 1185 if (property == None)
1186 goto DONE;
1187
896 multprop 1188 multprop
897 = x_get_window_property_as_lisp_data (dpyinfo, requestor, property, 1189 = x_get_window_property_as_lisp_data (dpyinfo, requestor, property,
898 QMULTIPLE, selection, true); 1190 QMULTIPLE, selection, true);
@@ -904,23 +1196,24 @@ x_handle_selection_request (struct selection_input_event *event)
904 /* Perform conversions. This can signal. */ 1196 /* Perform conversions. This can signal. */
905 for (j = 0; j < nselections; j++) 1197 for (j = 0; j < nselections; j++)
906 { 1198 {
907 Lisp_Object subtarget = AREF (multprop, 2*j); 1199 Lisp_Object subtarget = AREF (multprop, 2 * j);
908 Atom subproperty = symbol_to_x_atom (dpyinfo, 1200 Atom subproperty = symbol_to_x_atom (dpyinfo,
909 AREF (multprop, 2*j+1)); 1201 AREF (multprop, 2*j+1));
910 bool subsuccess = false; 1202 bool subsuccess = false;
911 1203
912 if (subproperty != None) 1204 if (subproperty != None)
913 subsuccess = x_convert_selection (selection_symbol, subtarget, 1205 subsuccess = x_convert_selection (selection_symbol, subtarget,
914 subproperty, true, dpyinfo, 1206 subproperty, dpyinfo,
915 use_alternate); 1207 use_alternate);
916 if (!subsuccess) 1208 if (!subsuccess)
917 ASET (multprop, 2*j+1, Qnil); 1209 ASET (multprop, 2 * j + 1, Qnil);
918 } 1210 }
1211
919 /* Save conversion results */ 1212 /* Save conversion results */
920 lisp_data_to_selection_data (dpyinfo, multprop, &cs); 1213 lisp_data_to_selection_data (dpyinfo, multprop, &cs);
921 1214
922 /* If cs.type is ATOM, change it to ATOM_PAIR. This is because 1215 /* If cs.type is ATOM, change it to ATOM_PAIR. This is
923 the parameters to a MULTIPLE are ATOM_PAIRs. */ 1216 because the parameters to a MULTIPLE are ATOM_PAIRs. */
924 1217
925 if (cs.type == XA_ATOM) 1218 if (cs.type == XA_ATOM)
926 cs.type = dpyinfo->Xatom_ATOM_PAIR; 1219 cs.type = dpyinfo->Xatom_ATOM_PAIR;
@@ -929,27 +1222,29 @@ x_handle_selection_request (struct selection_input_event *event)
929 cs.type, cs.format, PropModeReplace, 1222 cs.type, cs.format, PropModeReplace,
930 cs.data, cs.size); 1223 cs.data, cs.size);
931 success = true; 1224 success = true;
1225
1226 xfree (cs.data);
932 } 1227 }
933 else 1228 else
934 { 1229 {
935 if (property == None) 1230 if (property == None)
936 property = SELECTION_EVENT_TARGET (event); 1231 property = SELECTION_EVENT_TARGET (event);
1232
937 success = x_convert_selection (selection_symbol, 1233 success = x_convert_selection (selection_symbol,
938 target_symbol, property, 1234 target_symbol, property,
939 false, dpyinfo, 1235 dpyinfo, use_alternate);
940 use_alternate);
941 } 1236 }
942 1237
943 DONE: 1238 DONE:
944 1239
945 if (pushed)
946 selection_request_stack->converted = true;
947
948 if (success) 1240 if (success)
949 x_reply_selection_request (event, dpyinfo); 1241 x_reply_selection_request (event, dpyinfo);
950 else 1242 else
951 x_decline_selection_request (event); 1243 x_decline_selection_request (event);
952 1244
1245 if (pushed)
1246 selection_request_stack->converted = true;
1247
953 /* Run the `x-sent-selection-functions' abnormal hook. */ 1248 /* Run the `x-sent-selection-functions' abnormal hook. */
954 if (!NILP (Vx_sent_selection_functions) 1249 if (!NILP (Vx_sent_selection_functions)
955 && !BASE_EQ (Vx_sent_selection_functions, Qunbound)) 1250 && !BASE_EQ (Vx_sent_selection_functions, Qunbound))
@@ -960,19 +1255,18 @@ x_handle_selection_request (struct selection_input_event *event)
960 REALLY_DONE: 1255 REALLY_DONE:
961 1256
962 unbind_to (count, Qnil); 1257 unbind_to (count, Qnil);
1258 return;
963} 1259}
964 1260
965/* Perform the requested selection conversion, and write the data to 1261/* Perform the requested selection conversion, and write the data to
966 the converted_selections linked list, where it can be accessed by 1262 the converted_selections linked list, where it can be accessed by
967 x_reply_selection_request. If FOR_MULTIPLE, write out 1263 x_reply_selection_request.
968 the data even if conversion fails, using conversion_fail_tag.
969 1264
970 Return true if successful. */ 1265 Return true if successful. */
971 1266
972static bool 1267static bool
973x_convert_selection (Lisp_Object selection_symbol, 1268x_convert_selection (Lisp_Object selection_symbol, Lisp_Object target_symbol,
974 Lisp_Object target_symbol, Atom property, 1269 Atom property, struct x_display_info *dpyinfo,
975 bool for_multiple, struct x_display_info *dpyinfo,
976 bool use_alternate) 1270 bool use_alternate)
977{ 1271{
978 Lisp_Object lisp_selection; 1272 Lisp_Object lisp_selection;
@@ -988,33 +1282,16 @@ x_convert_selection (Lisp_Object selection_symbol,
988 /* A nil return value means we can't perform the conversion. */ 1282 /* A nil return value means we can't perform the conversion. */
989 if (NILP (lisp_selection) 1283 if (NILP (lisp_selection)
990 || (CONSP (lisp_selection) && NILP (XCDR (lisp_selection)))) 1284 || (CONSP (lisp_selection) && NILP (XCDR (lisp_selection))))
991 { 1285 return false;
992 if (for_multiple)
993 {
994 cs = xmalloc (sizeof *cs);
995 cs->data = ((unsigned char *)
996 &selection_request_stack->conversion_fail_tag);
997 cs->size = 1;
998 cs->format = 32;
999 cs->type = XA_ATOM;
1000 cs->nofree = true;
1001 cs->property = property;
1002 cs->wait_object = NULL;
1003 cs->next = frame->converted_selections;
1004 frame->converted_selections = cs;
1005 }
1006
1007 return false;
1008 }
1009 1286
1010 /* Otherwise, record the converted selection to binary. */ 1287 /* Otherwise, record the converted selection to binary. */
1011 cs = xmalloc (sizeof *cs); 1288 cs = xmalloc (sizeof *cs);
1012 cs->data = NULL; 1289 cs->data = NULL;
1013 cs->nofree = true; 1290 cs->string = Qnil;
1014 cs->property = property; 1291 cs->property = property;
1015 cs->wait_object = NULL;
1016 cs->next = frame->converted_selections; 1292 cs->next = frame->converted_selections;
1017 frame->converted_selections = cs; 1293 frame->converted_selections = cs;
1294
1018 lisp_data_to_selection_data (dpyinfo, lisp_selection, cs); 1295 lisp_data_to_selection_data (dpyinfo, lisp_selection, cs);
1019 return true; 1296 return true;
1020} 1297}
@@ -1129,14 +1406,14 @@ x_clear_frame_selections (struct frame *f)
1129 while (CONSP (t->Vselection_alist) 1406 while (CONSP (t->Vselection_alist)
1130 && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist))))))) 1407 && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist)))))))
1131 { 1408 {
1132 selection = Fcar (Fcar (t->Vselection_alist)); 1409 selection = CAR (CAR (t->Vselection_alist));
1133 1410
1134 if (!x_should_preserve_selection (selection)) 1411 if (!x_should_preserve_selection (selection))
1135 /* Run the `x-lost-selection-functions' abnormal hook. */ 1412 /* Run the `x-lost-selection-functions' abnormal hook. */
1136 CALLN (Frun_hook_with_args, Qx_lost_selection_functions, 1413 CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
1137 selection); 1414 selection);
1138 else 1415 else
1139 lost = Fcons (Fcar (t->Vselection_alist), lost); 1416 lost = Fcons (CAR (t->Vselection_alist), lost);
1140 1417
1141 tset_selection_alist (t, XCDR (t->Vselection_alist)); 1418 tset_selection_alist (t, XCDR (t->Vselection_alist));
1142 } 1419 }
@@ -1274,6 +1551,10 @@ void
1274x_handle_property_notify (const XPropertyEvent *event) 1551x_handle_property_notify (const XPropertyEvent *event)
1275{ 1552{
1276 struct prop_location *rest; 1553 struct prop_location *rest;
1554 struct transfer *next;
1555#ifdef TRACE_SELECTION
1556 char *name;
1557#endif
1277 1558
1278 for (rest = property_change_wait_list; rest; rest = rest->next) 1559 for (rest = property_change_wait_list; rest; rest = rest->next)
1279 { 1560 {
@@ -1283,9 +1564,16 @@ x_handle_property_notify (const XPropertyEvent *event)
1283 && rest->display == event->display 1564 && rest->display == event->display
1284 && rest->desired_state == event->state) 1565 && rest->desired_state == event->state)
1285 { 1566 {
1567#ifdef TRACE_SELECTION
1568 name = XGetAtomName (event->display, event->atom);
1569
1286 TRACE2 ("Expected %s of property %s", 1570 TRACE2 ("Expected %s of property %s",
1287 (event->state == PropertyDelete ? "deletion" : "change"), 1571 (event->state == PropertyDelete ? "deletion" : "change"),
1288 XGetAtomName (event->display, event->atom)); 1572 name ? name : "unknown");
1573
1574 if (name)
1575 XFree (name);
1576#endif
1289 1577
1290 rest->arrived = true; 1578 rest->arrived = true;
1291 1579
@@ -1297,6 +1585,26 @@ x_handle_property_notify (const XPropertyEvent *event)
1297 return; 1585 return;
1298 } 1586 }
1299 } 1587 }
1588
1589 /* Look for a property change for an outstanding selection
1590 transfer. */
1591 next = outstanding_transfers.next;
1592 while (next != &outstanding_transfers)
1593 {
1594 if (next->dpyinfo->display == event->display
1595 && next->requestor == event->window
1596 && next->data.property == event->atom
1597 && event->state == PropertyDelete)
1598 {
1599 TRACE1 ("Expected PropertyDelete event arrived from the"
1600 " requestor window %lx", next->requestor);
1601
1602 x_continue_selection_transfer (next);
1603 return;
1604 }
1605
1606 next = next->next;
1607 }
1300} 1608}
1301 1609
1302static void 1610static void
@@ -1450,10 +1758,10 @@ x_get_window_property (Display *display, Window window, Atom property,
1450 /* Maximum value for TOTAL_SIZE. It cannot exceed PTRDIFF_MAX - 1 1758 /* Maximum value for TOTAL_SIZE. It cannot exceed PTRDIFF_MAX - 1
1451 and SIZE_MAX - 1, for an extra byte at the end. And it cannot 1759 and SIZE_MAX - 1, for an extra byte at the end. And it cannot
1452 exceed LONG_MAX * X_LONG_SIZE, for XGetWindowProperty. */ 1760 exceed LONG_MAX * X_LONG_SIZE, for XGetWindowProperty. */
1453 ptrdiff_t total_size_max = 1761 ptrdiff_t total_size_max
1454 ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX 1762 = ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX
1455 ? min (PTRDIFF_MAX, SIZE_MAX) - 1 1763 ? min (PTRDIFF_MAX, SIZE_MAX) - 1
1456 : LONG_MAX * x_long_size); 1764 : LONG_MAX * x_long_size);
1457 1765
1458 block_input (); 1766 block_input ();
1459 1767
@@ -1946,10 +2254,14 @@ static void
1946lisp_data_to_selection_data (struct x_display_info *dpyinfo, 2254lisp_data_to_selection_data (struct x_display_info *dpyinfo,
1947 Lisp_Object obj, struct selection_data *cs) 2255 Lisp_Object obj, struct selection_data *cs)
1948{ 2256{
1949 Lisp_Object type = Qnil; 2257 Lisp_Object type;
2258 char **name_buffer;
2259
2260 USE_SAFE_ALLOCA;
2261
2262 type = Qnil;
1950 2263
1951 eassert (cs != NULL); 2264 eassert (cs != NULL);
1952 cs->nofree = false;
1953 2265
1954 if (CONSP (obj) && SYMBOLP (XCAR (obj))) 2266 if (CONSP (obj) && SYMBOLP (XCAR (obj)))
1955 { 2267 {
@@ -1959,8 +2271,10 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
1959 obj = XCAR (obj); 2271 obj = XCAR (obj);
1960 } 2272 }
1961 2273
2274 /* This is not the same as declining. */
2275
1962 if (EQ (obj, QNULL) || (EQ (type, QNULL))) 2276 if (EQ (obj, QNULL) || (EQ (type, QNULL)))
1963 { /* This is not the same as declining */ 2277 {
1964 cs->format = 32; 2278 cs->format = 32;
1965 cs->size = 0; 2279 cs->size = 0;
1966 cs->data = NULL; 2280 cs->data = NULL;
@@ -1971,12 +2285,14 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
1971 if (SCHARS (obj) < SBYTES (obj)) 2285 if (SCHARS (obj) < SBYTES (obj))
1972 /* OBJ is a multibyte string containing a non-ASCII char. */ 2286 /* OBJ is a multibyte string containing a non-ASCII char. */
1973 signal_error ("Non-ASCII string must be encoded in advance", obj); 2287 signal_error ("Non-ASCII string must be encoded in advance", obj);
2288
1974 if (NILP (type)) 2289 if (NILP (type))
1975 type = QSTRING; 2290 type = QSTRING;
2291
1976 cs->format = 8; 2292 cs->format = 8;
1977 cs->size = SBYTES (obj); 2293 cs->size = -1;
1978 cs->data = SDATA (obj); 2294 cs->data = NULL;
1979 cs->nofree = true; 2295 cs->string = obj;
1980 } 2296 }
1981 else if (SYMBOLP (obj)) 2297 else if (SYMBOLP (obj))
1982 { 2298 {
@@ -2048,8 +2364,19 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
2048 x_atoms = data; 2364 x_atoms = data;
2049 cs->format = 32; 2365 cs->format = 32;
2050 cs->size = size; 2366 cs->size = size;
2051 for (i = 0; i < size; i++) 2367
2052 x_atoms[i] = symbol_to_x_atom (dpyinfo, AREF (obj, i)); 2368 if (size == 1)
2369 x_atoms[0] = symbol_to_x_atom (dpyinfo, AREF (obj, i));
2370 else
2371 {
2372 SAFE_NALLOCA (name_buffer, sizeof *x_atoms, size);
2373
2374 for (i = 0; i < size; i++)
2375 name_buffer[i] = SSDATA (SYMBOL_NAME (AREF (obj, i)));
2376
2377 x_intern_atoms (dpyinfo, name_buffer, size,
2378 x_atoms);
2379 }
2053 } 2380 }
2054 else 2381 else
2055 /* This vector is an INTEGER set, or something like it */ 2382 /* This vector is an INTEGER set, or something like it */
@@ -2091,6 +2418,8 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
2091 signal_error (/* Qselection_error */ "Unrecognized selection data", obj); 2418 signal_error (/* Qselection_error */ "Unrecognized selection data", obj);
2092 2419
2093 cs->type = symbol_to_x_atom (dpyinfo, type); 2420 cs->type = symbol_to_x_atom (dpyinfo, type);
2421
2422 SAFE_FREE ();
2094} 2423}
2095 2424
2096static Lisp_Object 2425static Lisp_Object
@@ -2618,8 +2947,8 @@ x_check_property_data (Lisp_Object data)
2618 XClientMessageEvent). */ 2947 XClientMessageEvent). */
2619 2948
2620void 2949void
2621x_fill_property_data (Display *dpy, Lisp_Object data, void *ret, 2950x_fill_property_data (struct x_display_info *dpyinfo, Lisp_Object data,
2622 int nelements_max, int format) 2951 void *ret, int nelements_max, int format)
2623{ 2952{
2624 unsigned long val; 2953 unsigned long val;
2625 unsigned long *d32 = (unsigned long *) ret; 2954 unsigned long *d32 = (unsigned long *) ret;
@@ -2654,7 +2983,7 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret,
2654 else if (STRINGP (o)) 2983 else if (STRINGP (o))
2655 { 2984 {
2656 block_input (); 2985 block_input ();
2657 val = XInternAtom (dpy, SSDATA (o), False); 2986 val = x_intern_cached_atom (dpyinfo, SSDATA (o), false);
2658 unblock_input (); 2987 unblock_input ();
2659 } 2988 }
2660 else 2989 else
@@ -2942,7 +3271,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
2942 3271
2943 memset (event.xclient.data.l, 0, sizeof (event.xclient.data.l)); 3272 memset (event.xclient.data.l, 0, sizeof (event.xclient.data.l));
2944 /* event.xclient.data can hold 20 chars, 10 shorts, or 5 longs. */ 3273 /* event.xclient.data can hold 20 chars, 10 shorts, or 5 longs. */
2945 x_fill_property_data (dpyinfo->display, values, event.xclient.data.b, 3274 x_fill_property_data (dpyinfo, values, event.xclient.data.b,
2946 5 * 32 / event.xclient.format, 3275 5 * 32 / event.xclient.format,
2947 event.xclient.format); 3276 event.xclient.format);
2948 3277
@@ -3002,10 +3331,11 @@ syms_of_xselect (void)
3002 3331
3003 reading_selection_reply = Fcons (Qnil, Qnil); 3332 reading_selection_reply = Fcons (Qnil, Qnil);
3004 staticpro (&reading_selection_reply); 3333 staticpro (&reading_selection_reply);
3005
3006 staticpro (&property_change_reply); 3334 staticpro (&property_change_reply);
3007 3335
3008 /* FIXME: Duplicate definition in nsselect.c. */ 3336 outstanding_transfers.next = &outstanding_transfers;
3337 outstanding_transfers.last = &outstanding_transfers;
3338
3009 DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist, 3339 DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist,
3010 doc: /* An alist associating X Windows selection-types with functions. 3340 doc: /* An alist associating X Windows selection-types with functions.
3011These functions are called to convert the selection, with three args: 3341These functions are called to convert the selection, with three args:
@@ -3120,9 +3450,43 @@ Note that this does not affect setting or owning selections. */);
3120static void 3450static void
3121syms_of_xselect_for_pdumper (void) 3451syms_of_xselect_for_pdumper (void)
3122{ 3452{
3453 outstanding_transfers.next = &outstanding_transfers;
3454 outstanding_transfers.last = &outstanding_transfers;
3455
3123 reading_selection_window = 0; 3456 reading_selection_window = 0;
3124 reading_which_selection = 0; 3457 reading_which_selection = 0;
3125 property_change_wait_list = 0; 3458 property_change_wait_list = 0;
3126 prop_location_identifier = 0; 3459 prop_location_identifier = 0;
3127 property_change_reply = Fcons (Qnil, Qnil); 3460 property_change_reply = Fcons (Qnil, Qnil);
3128} 3461}
3462
3463void
3464mark_xselect (void)
3465{
3466 struct transfer *next;
3467 struct x_selection_request *frame;
3468 struct selection_data *cs;
3469
3470 /* Mark all the strings being used as selection data. A string that
3471 is still reachable is always reachable via either the selection
3472 request stack or the list of outstanding transfers. */
3473
3474 next = outstanding_transfers.next;
3475
3476 if (!next)
3477 /* syms_of_xselect has not yet been called. */
3478 return;
3479
3480 while (next != &outstanding_transfers)
3481 {
3482 mark_object (next->data.string);
3483 next = next->next;
3484 }
3485
3486 frame = selection_request_stack;
3487 for (; frame; frame = frame->last)
3488 {
3489 for (cs = frame->converted_selections; cs; cs = cs->next)
3490 mark_object (cs->string);
3491 }
3492}
diff --git a/src/xterm.c b/src/xterm.c
index cfd8c385d1d..60d48165650 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -26,6 +26,22 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
26 contains subroutines comprising the redisplay interface, setting up 26 contains subroutines comprising the redisplay interface, setting up
27 scroll bars and widgets, and handling input. 27 scroll bars and widgets, and handling input.
28 28
29 X WINDOW SYSTEM
30
31 The X Window System is a windowing system for bitmap graphics
32 displays which originated at MIT in 1984. Version 11, which is
33 currently supported by Emacs, first appeared in September 1987.
34
35 X has a long history and has been developed by many different
36 organizations over the years; at present, it is being primarily
37 developed by the X.Org Foundation. It is the main window system
38 that Emacs is developed and tested against, and X version 10 was
39 the first window system that Emacs was ported to. As a consequence
40 of its age and wide availability, X contains many idiosyncrasies,
41 but that has not prevented it from becoming the dominant free
42 window system, and the platform of reference for all GUI code in
43 Emacs.
44
29 Some of what is explained below also applies to the other window 45 Some of what is explained below also applies to the other window
30 systems that Emacs supports, to varying degrees. YMMV. 46 systems that Emacs supports, to varying degrees. YMMV.
31 47
@@ -555,7 +571,56 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
555 drop happening with the primary selection and synthetic button 571 drop happening with the primary selection and synthetic button
556 events (see `x_dnd_do_unsupported_drop'). That function implements 572 events (see `x_dnd_do_unsupported_drop'). That function implements
557 the OffiX drag-and-drop protocol by default. See 573 the OffiX drag-and-drop protocol by default. See
558 `x-dnd-handle-unsupported-drop' in `x-dnd.el' for more details. */ 574 `x-dnd-handle-unsupported-drop' in `x-dnd.el' for more details.
575
576 DISPLAY ERROR HANDLING
577
578 While error handling under X was originally designed solely as a
579 mechanism for the X server to report fatal errors to clients, most
580 clients (including Emacs) have adopted a system of "error traps" to
581 handle or discard these errors as they arrive. Discarding errors is
582 usually necessary when Emacs performs an X request that might fail:
583 for example, sending a message to a window that may no longer exist,
584 or might not exist at all. Handling errors is then necessary when
585 the detailed error must be reported to another piece of code: for
586 example, as a Lisp error.
587
588 It is not acceptable for Emacs to crash when it is sent invalid data
589 by another client, or by Lisp. As a result, errors must be caught
590 around Xlib functions generating requests containing resource
591 identifiers that could potentially be invalid, such as window or
592 atom identifiers provided in a client message from another program,
593 or a child window ID obtained through XTranslateCoordinates that may
594 refer to a window that has been deleted in the meantime.
595
596 There are two sets of functions used to perform this "error
597 trapping". Which one should be used depends on what kind of
598 processing must be done on the error. The first consists of the
599 functions `x_ignore_errors_for_next_request' and
600 `x_stop_ignoring_errors', which ignore errors generated by requests
601 made in between a call to the first function and a corresponding
602 call to the second. They should be used for simple asynchronous
603 requests that do not require a reply from the X server: using them
604 instead of the second set improves performance, as they simply
605 record a range of request serials to ignore errors from, instead of
606 synchronizing with the X server to handle errors.
607
608 The second set consists of the following functions:
609
610 - x_catch_errors_with_handler
611 - x_catch_errors
612 - x_uncatch_errors_after_check
613 - x_uncatch_errors
614 - x_check_errors
615 - x_had_errors_p
616 - x_clear_errors
617
618 Callers using this set should consult the comment(s) on top of the
619 aformentioned functions. They should not be used when the requests
620 being made do not require roundtrips to the X server, and obtaining
621 the details of any error generated is unecessary, as
622 `x_uncatch_errors' will always synchronize with the X server, which
623 is a potentially slow operation. */
559 624
560#include <config.h> 625#include <config.h>
561#include <stdlib.h> 626#include <stdlib.h>
@@ -574,7 +639,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
574#ifdef USE_XCB 639#ifdef USE_XCB
575#include <xcb/xproto.h> 640#include <xcb/xproto.h>
576#include <xcb/xcb.h> 641#include <xcb/xcb.h>
577#include <xcb/xcb_aux.h>
578#endif 642#endif
579 643
580/* If we have Xfixes extension, use it for pointer blanking. */ 644/* If we have Xfixes extension, use it for pointer blanking. */
@@ -1052,6 +1116,20 @@ static const struct x_atom_ref x_atom_refs[] =
1052 /* Old OffiX (a.k.a. old KDE) drop protocol support. */ 1116 /* Old OffiX (a.k.a. old KDE) drop protocol support. */
1053 ATOM_REFS_INIT ("DndProtocol", Xatom_DndProtocol) 1117 ATOM_REFS_INIT ("DndProtocol", Xatom_DndProtocol)
1054 ATOM_REFS_INIT ("_DND_PROTOCOL", Xatom_DND_PROTOCOL) 1118 ATOM_REFS_INIT ("_DND_PROTOCOL", Xatom_DND_PROTOCOL)
1119 /* Here are some atoms that are not actually used from C, just
1120 defined to make replying to selection requests fast. */
1121 ATOM_REFS_INIT ("text/plain;charset=utf-8", Xatom_text_plain_charset_utf_8)
1122 ATOM_REFS_INIT ("LENGTH", Xatom_LENGTH)
1123 ATOM_REFS_INIT ("FILE_NAME", Xatom_FILE_NAME)
1124 ATOM_REFS_INIT ("CHARACTER_POSITION", Xatom_CHARACTER_POSITION)
1125 ATOM_REFS_INIT ("LINE_NUMBER", Xatom_LINE_NUMBER)
1126 ATOM_REFS_INIT ("COLUMN_NUMBER", Xatom_COLUMN_NUMBER)
1127 ATOM_REFS_INIT ("OWNER_OS", Xatom_OWNER_OS)
1128 ATOM_REFS_INIT ("HOST_NAME", Xatom_HOST_NAME)
1129 ATOM_REFS_INIT ("USER", Xatom_USER)
1130 ATOM_REFS_INIT ("CLASS", Xatom_CLASS)
1131 ATOM_REFS_INIT ("NAME", Xatom_NAME)
1132 ATOM_REFS_INIT ("SAVE_TARGETS", Xatom_SAVE_TARGETS)
1055 }; 1133 };
1056 1134
1057enum 1135enum
@@ -2509,7 +2587,7 @@ xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
2509 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom; 2587 *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
2510 *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window; 2588 *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window;
2511 2589
2512 x_ignore_errors_for_next_request (dpyinfo); 2590 x_ignore_errors_for_next_request (dpyinfo, 0);
2513 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2591 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2514 x_stop_ignoring_errors (dpyinfo); 2592 x_stop_ignoring_errors (dpyinfo);
2515} 2593}
@@ -2536,7 +2614,7 @@ xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source,
2536 msg.xclient.data.b[18] = 0; 2614 msg.xclient.data.b[18] = 0;
2537 msg.xclient.data.b[19] = 0; 2615 msg.xclient.data.b[19] = 0;
2538 2616
2539 x_ignore_errors_for_next_request (dpyinfo); 2617 x_ignore_errors_for_next_request (dpyinfo, 0);
2540 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2618 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2541 x_stop_ignoring_errors (dpyinfo); 2619 x_stop_ignoring_errors (dpyinfo);
2542} 2620}
@@ -2567,7 +2645,7 @@ xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source,
2567 msg.xclient.data.b[18] = 0; 2645 msg.xclient.data.b[18] = 0;
2568 msg.xclient.data.b[19] = 0; 2646 msg.xclient.data.b[19] = 0;
2569 2647
2570 x_ignore_errors_for_next_request (dpyinfo); 2648 x_ignore_errors_for_next_request (dpyinfo, 0);
2571 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2649 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2572 x_stop_ignoring_errors (dpyinfo); 2650 x_stop_ignoring_errors (dpyinfo);
2573} 2651}
@@ -2626,7 +2704,7 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source,
2626 msg.xclient.data.b[18] = 0; 2704 msg.xclient.data.b[18] = 0;
2627 msg.xclient.data.b[19] = 0; 2705 msg.xclient.data.b[19] = 0;
2628 2706
2629 x_ignore_errors_for_next_request (dpyinfo); 2707 x_ignore_errors_for_next_request (dpyinfo, 0);
2630 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); 2708 XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
2631 x_stop_ignoring_errors (dpyinfo); 2709 x_stop_ignoring_errors (dpyinfo);
2632} 2710}
@@ -2921,7 +2999,7 @@ x_dnd_free_toplevels (bool display_alive)
2921 if (n_windows) 2999 if (n_windows)
2922 { 3000 {
2923 eassume (dpyinfo); 3001 eassume (dpyinfo);
2924 x_ignore_errors_for_next_request (dpyinfo); 3002 x_ignore_errors_for_next_request (dpyinfo, 0);
2925 3003
2926 for (i = 0; i < n_windows; ++i) 3004 for (i = 0; i < n_windows; ++i)
2927 { 3005 {
@@ -3058,7 +3136,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3058 0, 0); 3136 0, 0);
3059 get_property_cookies[i] 3137 get_property_cookies[i]
3060 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i], 3138 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
3061 (xcb_atom_t) dpyinfo->Xatom_wm_state, XCB_ATOM_ANY, 3139 (xcb_atom_t) dpyinfo->Xatom_wm_state, 0,
3062 0, 2); 3140 0, 2);
3063 xm_property_cookies[i] 3141 xm_property_cookies[i]
3064 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i], 3142 = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
@@ -3069,7 +3147,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3069 = xcb_get_property (dpyinfo->xcb_connection, 0, 3147 = xcb_get_property (dpyinfo->xcb_connection, 0,
3070 (xcb_window_t) toplevels[i], 3148 (xcb_window_t) toplevels[i],
3071 (xcb_atom_t) dpyinfo->Xatom_net_frame_extents, 3149 (xcb_atom_t) dpyinfo->Xatom_net_frame_extents,
3072 XCB_ATOM_CARDINAL, 0, 4); 3150 XA_CARDINAL, 0, 4);
3073 get_geometry_cookies[i] 3151 get_geometry_cookies[i]
3074 = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]); 3152 = xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
3075 3153
@@ -3197,7 +3275,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3197 { 3275 {
3198 if (xcb_get_property_value_length (extent_property_reply) == 16 3276 if (xcb_get_property_value_length (extent_property_reply) == 16
3199 && extent_property_reply->format == 32 3277 && extent_property_reply->format == 32
3200 && extent_property_reply->type == XCB_ATOM_CARDINAL) 3278 && extent_property_reply->type == XA_CARDINAL)
3201 { 3279 {
3202 fextents = xcb_get_property_value (extent_property_reply); 3280 fextents = xcb_get_property_value (extent_property_reply);
3203 frame_extents[0] = fextents[0]; 3281 frame_extents[0] = fextents[0];
@@ -3291,7 +3369,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3291 3369
3292 if (dpyinfo->xshape_supported_p) 3370 if (dpyinfo->xshape_supported_p)
3293 { 3371 {
3294 x_ignore_errors_for_next_request (dpyinfo); 3372 x_ignore_errors_for_next_request (dpyinfo, 0);
3295 XShapeSelectInput (dpyinfo->display, 3373 XShapeSelectInput (dpyinfo->display,
3296 toplevels[i], 3374 toplevels[i],
3297 ShapeNotifyMask); 3375 ShapeNotifyMask);
@@ -3456,7 +3534,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
3456 } 3534 }
3457#endif 3535#endif
3458 3536
3459 x_ignore_errors_for_next_request (dpyinfo); 3537 x_ignore_errors_for_next_request (dpyinfo, 0);
3460 XSelectInput (dpyinfo->display, toplevels[i], 3538 XSelectInput (dpyinfo->display, toplevels[i],
3461 (attrs.your_event_mask 3539 (attrs.your_event_mask
3462 | StructureNotifyMask 3540 | StructureNotifyMask
@@ -3571,13 +3649,13 @@ x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
3571 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, 3649 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3572 (xcb_window_t) wdesc, 3650 (xcb_window_t) wdesc,
3573 (xcb_atom_t) dpyinfo->Xatom_XdndProxy, 3651 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3574 XCB_ATOM_WINDOW, 0, 1); 3652 XA_WINDOW, 0, 1);
3575 3653
3576 if (proto_out) 3654 if (proto_out)
3577 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, 3655 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3578 (xcb_window_t) wdesc, 3656 (xcb_window_t) wdesc,
3579 (xcb_atom_t) dpyinfo->Xatom_XdndAware, 3657 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3580 XCB_ATOM_ATOM, 0, 1); 3658 XA_ATOM, 0, 1);
3581 3659
3582 if (proxy_out) 3660 if (proxy_out)
3583 { 3661 {
@@ -3589,7 +3667,7 @@ x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
3589 else 3667 else
3590 { 3668 {
3591 if (reply->format == 32 3669 if (reply->format == 32
3592 && reply->type == XCB_ATOM_WINDOW 3670 && reply->type == XA_WINDOW
3593 && (xcb_get_property_value_length (reply) >= 4)) 3671 && (xcb_get_property_value_length (reply) >= 4))
3594 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply); 3672 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3595 3673
@@ -3607,7 +3685,7 @@ x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
3607 else 3685 else
3608 { 3686 {
3609 if (reply->format == 32 3687 if (reply->format == 32
3610 && reply->type == XCB_ATOM_ATOM 3688 && reply->type == XA_ATOM
3611 && (xcb_get_property_value_length (reply) >= 4)) 3689 && (xcb_get_property_value_length (reply) >= 4))
3612 *proto_out = (int) *(xcb_atom_t *) xcb_get_property_value (reply); 3690 *proto_out = (int) *(xcb_atom_t *) xcb_get_property_value (reply);
3613 3691
@@ -3791,15 +3869,15 @@ x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
3791 wmstate_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, 3869 wmstate_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3792 (xcb_window_t) window, 3870 (xcb_window_t) window,
3793 (xcb_atom_t) dpyinfo->Xatom_wm_state, 3871 (xcb_atom_t) dpyinfo->Xatom_wm_state,
3794 XCB_ATOM_ANY, 0, 2); 3872 0, 0, 2);
3795 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, 3873 xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3796 (xcb_window_t) window, 3874 (xcb_window_t) window,
3797 (xcb_atom_t) dpyinfo->Xatom_XdndAware, 3875 (xcb_atom_t) dpyinfo->Xatom_XdndAware,
3798 XCB_ATOM_ATOM, 0, 1); 3876 XA_ATOM, 0, 1);
3799 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, 3877 xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3800 (xcb_window_t) window, 3878 (xcb_window_t) window,
3801 (xcb_atom_t) dpyinfo->Xatom_XdndProxy, 3879 (xcb_atom_t) dpyinfo->Xatom_XdndProxy,
3802 XCB_ATOM_WINDOW, 0, 1); 3880 XA_WINDOW, 0, 1);
3803 xm_style_cookie = xcb_get_property (dpyinfo->xcb_connection, 0, 3881 xm_style_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
3804 (xcb_window_t) window, 3882 (xcb_window_t) window,
3805 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO, 3883 (xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
@@ -3846,7 +3924,7 @@ x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
3846 else 3924 else
3847 { 3925 {
3848 if (reply->format == 32 3926 if (reply->format == 32
3849 && reply->type == XCB_ATOM_WINDOW 3927 && reply->type == XA_WINDOW
3850 && (xcb_get_property_value_length (reply) >= 4)) 3928 && (xcb_get_property_value_length (reply) >= 4))
3851 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply); 3929 *proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
3852 3930
@@ -3962,6 +4040,12 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
3962 if (owner != FRAME_X_WINDOW (f)) 4040 if (owner != FRAME_X_WINDOW (f))
3963 return; 4041 return;
3964 4042
4043 /* mouse-drag-and-drop-region will immediately deactivate the mark
4044 after this is set. Make sure the primary selection is not
4045 clobbered in that case by setting `deactivate-mark' to
4046 Qdont_save. */
4047 Vdeactivate_mark = Qdont_save;
4048
3965 event.xbutton.window = child; 4049 event.xbutton.window = child;
3966 event.xbutton.subwindow = None; 4050 event.xbutton.subwindow = None;
3967 event.xbutton.x = dest_x; 4051 event.xbutton.x = dest_x;
@@ -3975,7 +4059,7 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
3975 event.xbutton.type = ButtonPress; 4059 event.xbutton.type = ButtonPress;
3976 event.xbutton.time = before + 1; 4060 event.xbutton.time = before + 1;
3977 4061
3978 x_ignore_errors_for_next_request (dpyinfo); 4062 x_ignore_errors_for_next_request (dpyinfo, 0);
3979 XSendEvent (dpyinfo->display, child, 4063 XSendEvent (dpyinfo->display, child,
3980 True, ButtonPressMask, &event); 4064 True, ButtonPressMask, &event);
3981 4065
@@ -4487,7 +4571,7 @@ x_dnd_send_enter (struct frame *f, Window target, Window toplevel,
4487 so we don't have to set it again. */ 4571 so we don't have to set it again. */
4488 x_dnd_init_type_lists = true; 4572 x_dnd_init_type_lists = true;
4489 4573
4490 x_ignore_errors_for_next_request (dpyinfo); 4574 x_ignore_errors_for_next_request (dpyinfo, 0);
4491 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4575 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4492 x_stop_ignoring_errors (dpyinfo); 4576 x_stop_ignoring_errors (dpyinfo);
4493} 4577}
@@ -4559,7 +4643,7 @@ x_dnd_send_position (struct frame *f, Window target, Window toplevel,
4559 return; 4643 return;
4560 } 4644 }
4561 4645
4562 x_ignore_errors_for_next_request (dpyinfo); 4646 x_ignore_errors_for_next_request (dpyinfo, 0);
4563 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4647 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4564 x_stop_ignoring_errors (dpyinfo); 4648 x_stop_ignoring_errors (dpyinfo);
4565 4649
@@ -4586,7 +4670,7 @@ x_dnd_send_leave (struct frame *f, Window target, Window toplevel)
4586 x_dnd_waiting_for_status_window = None; 4670 x_dnd_waiting_for_status_window = None;
4587 x_dnd_pending_send_position.type = 0; 4671 x_dnd_pending_send_position.type = 0;
4588 4672
4589 x_ignore_errors_for_next_request (dpyinfo); 4673 x_ignore_errors_for_next_request (dpyinfo, 0);
4590 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4674 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4591 x_stop_ignoring_errors (dpyinfo); 4675 x_stop_ignoring_errors (dpyinfo);
4592} 4676}
@@ -4619,7 +4703,7 @@ x_dnd_send_drop (struct frame *f, Window target, Window toplevel,
4619 if (supported >= 1) 4703 if (supported >= 1)
4620 msg.xclient.data.l[2] = timestamp; 4704 msg.xclient.data.l[2] = timestamp;
4621 4705
4622 x_ignore_errors_for_next_request (dpyinfo); 4706 x_ignore_errors_for_next_request (dpyinfo, 0);
4623 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); 4707 XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
4624 x_stop_ignoring_errors (dpyinfo); 4708 x_stop_ignoring_errors (dpyinfo);
4625 return true; 4709 return true;
@@ -6731,7 +6815,7 @@ x_set_frame_alpha (struct frame *f)
6731 Do this unconditionally as this function is called on reparent when 6815 Do this unconditionally as this function is called on reparent when
6732 alpha has not changed on the frame. */ 6816 alpha has not changed on the frame. */
6733 6817
6734 x_ignore_errors_for_next_request (dpyinfo); 6818 x_ignore_errors_for_next_request (dpyinfo, 0);
6735 6819
6736 if (!FRAME_PARENT_FRAME (f)) 6820 if (!FRAME_PARENT_FRAME (f))
6737 { 6821 {
@@ -6907,6 +6991,7 @@ static void
6907x_sync_wait_for_frame_drawn_event (struct frame *f) 6991x_sync_wait_for_frame_drawn_event (struct frame *f)
6908{ 6992{
6909 XEvent event; 6993 XEvent event;
6994 struct x_display_info *dpyinfo;
6910 6995
6911 if (!FRAME_X_WAITING_FOR_DRAW (f) 6996 if (!FRAME_X_WAITING_FOR_DRAW (f)
6912 /* The compositing manager can't draw a frame if it is 6997 /* The compositing manager can't draw a frame if it is
@@ -6914,21 +6999,42 @@ x_sync_wait_for_frame_drawn_event (struct frame *f)
6914 || !FRAME_VISIBLE_P (f)) 6999 || !FRAME_VISIBLE_P (f))
6915 return; 7000 return;
6916 7001
7002 dpyinfo = FRAME_DISPLAY_INFO (f);
7003
6917 /* Wait for the frame drawn message to arrive. */ 7004 /* Wait for the frame drawn message to arrive. */
6918 if (x_if_event (FRAME_X_DISPLAY (f), &event, 7005 if (x_if_event (FRAME_X_DISPLAY (f), &event,
6919 x_sync_is_frame_drawn_event, (XPointer) f, 7006 x_sync_is_frame_drawn_event, (XPointer) f,
6920 make_timespec (1, 0))) 7007 make_timespec (1, 0)))
6921 { 7008 {
6922 /* TODO: display this warning in the echo area. */ 7009 /* The first time a draw hangs, treat it as a random fluctuation
6923 fprintf (stderr, "Warning: compositing manager spent more than 1 second " 7010 on the part of the compositor. If the next draw continues to
6924 "drawing a frame. Frame synchronization has been disabled\n"); 7011 hang, disable frame synchronization. */
6925 FRAME_X_OUTPUT (f)->use_vsync_p = false; 7012 if (FRAME_X_DRAW_JUST_HUNG (f))
7013 {
7014 fprintf (stderr, "Warning: compositing manager spent more than 1 "
7015 "second drawing a frame. Frame synchronization has "
7016 "been disabled\n");
7017 FRAME_X_OUTPUT (f)->use_vsync_p = false;
7018
7019 /* Remove the compositor bypass property from the outer
7020 window. */
7021 XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
7022 dpyinfo->Xatom_net_wm_bypass_compositor);
6926 7023
6927 /* Also change the frame parameter to reflect the new state. */ 7024 /* Also change the frame parameter to reflect the new
6928 store_frame_param (f, Quse_frame_synchronization, Qnil); 7025 state. */
7026 store_frame_param (f, Quse_frame_synchronization, Qnil);
7027 }
7028 else
7029 {
7030 fprintf (stderr, "Warning: compositing manager spent more than 1 "
7031 "second drawing a frame. Frame synchronization will be "
7032 "disabled if this happens again\n");
7033 FRAME_X_DRAW_JUST_HUNG (f) = true;
7034 }
6929 } 7035 }
6930 else 7036 else
6931 x_sync_note_frame_times (FRAME_DISPLAY_INFO (f), f, &event); 7037 x_sync_note_frame_times (dpyinfo, f, &event);
6932 7038
6933 FRAME_X_WAITING_FOR_DRAW (f) = false; 7039 FRAME_X_WAITING_FOR_DRAW (f) = false;
6934} 7040}
@@ -7128,8 +7234,26 @@ static void
7128x_sync_handle_frame_drawn (struct x_display_info *dpyinfo, 7234x_sync_handle_frame_drawn (struct x_display_info *dpyinfo,
7129 XEvent *message, struct frame *f) 7235 XEvent *message, struct frame *f)
7130{ 7236{
7237 XSyncValue value, counter;
7238
7131 if (FRAME_OUTER_WINDOW (f) == message->xclient.window) 7239 if (FRAME_OUTER_WINDOW (f) == message->xclient.window)
7132 FRAME_X_WAITING_FOR_DRAW (f) = false; 7240 {
7241 counter = FRAME_X_COUNTER_VALUE (f);
7242
7243 /* Check that the counter in the message is the same as the
7244 counter in the frame. */
7245 XSyncIntsToValue (&value,
7246 message->xclient.data.l[0] & 0xffffffff,
7247 message->xclient.data.l[1] & 0xffffffff);
7248
7249 if (XSyncValueEqual (value, counter))
7250 FRAME_X_WAITING_FOR_DRAW (f) = false;
7251
7252 /* As long as a _NET_WM_FRAME_DRAWN message arrives, we know
7253 that the compositor is still sending events, so avoid timing
7254 out. */
7255 FRAME_X_DRAW_JUST_HUNG (f) = false;
7256 }
7133 7257
7134 x_sync_note_frame_times (dpyinfo, f, message); 7258 x_sync_note_frame_times (dpyinfo, f, message);
7135} 7259}
@@ -10959,6 +11083,31 @@ x_clear_frame (struct frame *f)
10959 unblock_input (); 11083 unblock_input ();
10960} 11084}
10961 11085
11086/* Send a message to frame F telling the event loop to track whether
11087 or not an hourglass is being displayed. This is required to ignore
11088 the right events when the hourglass is mapped without callig XSync
11089 after displaying or hiding the hourglass. */
11090
11091static void
11092x_send_hourglass_message (struct frame *f, bool hourglass_enabled)
11093{
11094 struct x_display_info *dpyinfo;
11095 XEvent msg;
11096
11097 dpyinfo = FRAME_DISPLAY_INFO (f);
11098 memset (&msg, 0, sizeof msg);
11099
11100 msg.xclient.type = ClientMessage;
11101 msg.xclient.message_type
11102 = dpyinfo->Xatom_EMACS_TMP;
11103 msg.xclient.format = 8;
11104 msg.xclient.window = FRAME_X_WINDOW (f);
11105 msg.xclient.data.b[0] = hourglass_enabled ? 1 : 0;
11106
11107 XSendEvent (dpyinfo->display, FRAME_X_WINDOW (f),
11108 False, NoEventMask, &msg);
11109}
11110
10962/* RIF: Show hourglass cursor on frame F. */ 11111/* RIF: Show hourglass cursor on frame F. */
10963 11112
10964static void 11113static void
@@ -10979,14 +11128,14 @@ x_show_hourglass (struct frame *f)
10979 if (popup_activated ()) 11128 if (popup_activated ())
10980 return; 11129 return;
10981 11130
11131 x_send_hourglass_message (f, true);
11132
10982#ifdef USE_X_TOOLKIT 11133#ifdef USE_X_TOOLKIT
10983 if (x->widget) 11134 if (x->widget)
10984#else 11135#else
10985 if (FRAME_OUTER_WINDOW (f)) 11136 if (FRAME_OUTER_WINDOW (f))
10986#endif 11137#endif
10987 { 11138 {
10988 x->hourglass_p = true;
10989
10990 if (!x->hourglass_window) 11139 if (!x->hourglass_window)
10991 { 11140 {
10992#ifndef USE_XCB 11141#ifndef USE_XCB
@@ -11053,15 +11202,11 @@ x_hide_hourglass (struct frame *f)
11053 { 11202 {
11054#ifndef USE_XCB 11203#ifndef USE_XCB
11055 XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window); 11204 XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
11056 /* Sync here because XTread_socket looks at the
11057 hourglass_p flag that is reset to zero below. */
11058 XSync (FRAME_X_DISPLAY (f), False);
11059#else 11205#else
11060 xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection, 11206 xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
11061 (xcb_window_t) x->hourglass_window); 11207 (xcb_window_t) x->hourglass_window);
11062 xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection);
11063#endif 11208#endif
11064 x->hourglass_p = false; 11209 x_send_hourglass_message (f, false);
11065 } 11210 }
11066} 11211}
11067 11212
@@ -11185,21 +11330,32 @@ XTflash (struct frame *f)
11185static void 11330static void
11186XTring_bell (struct frame *f) 11331XTring_bell (struct frame *f)
11187{ 11332{
11188 if (FRAME_X_DISPLAY (f)) 11333 struct x_display_info *dpyinfo;
11334
11335 if (!FRAME_X_DISPLAY (f))
11336 return;
11337
11338 dpyinfo = FRAME_DISPLAY_INFO (f);
11339
11340 if (visible_bell)
11341 XTflash (f);
11342 else
11189 { 11343 {
11190 if (visible_bell) 11344 /* When Emacs is untrusted, Bell requests sometimes generate
11191 XTflash (f); 11345 Access errors. This is not in the security extension
11192 else 11346 specification but seems to be a bug in the X consortium XKB
11193 { 11347 implementation. */
11194 block_input (); 11348
11349 block_input ();
11350 x_ignore_errors_for_next_request (dpyinfo, 0);
11195#ifdef HAVE_XKB 11351#ifdef HAVE_XKB
11196 XkbBell (FRAME_X_DISPLAY (f), None, 0, None); 11352 XkbBell (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, None);
11197#else 11353#else
11198 XBell (FRAME_X_DISPLAY (f), 0); 11354 XBell (FRAME_X_DISPLAY (f), 0);
11199#endif 11355#endif
11200 XFlush (FRAME_X_DISPLAY (f)); 11356 XFlush (FRAME_X_DISPLAY (f));
11201 unblock_input (); 11357 x_stop_ignoring_errors (dpyinfo);
11202 } 11358 unblock_input ();
11203 } 11359 }
11204} 11360}
11205 11361
@@ -11445,7 +11601,7 @@ x_frame_highlight (struct frame *f)
11445 the window-manager in use, tho something more is at play since I've been 11601 the window-manager in use, tho something more is at play since I've been
11446 using that same window-manager binary for ever. Let's not crash just 11602 using that same window-manager binary for ever. Let's not crash just
11447 because of this (bug#9310). */ 11603 because of this (bug#9310). */
11448 x_ignore_errors_for_next_request (dpyinfo); 11604 x_ignore_errors_for_next_request (dpyinfo, 0);
11449 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 11605 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11450 f->output_data.x->border_pixel); 11606 f->output_data.x->border_pixel);
11451 x_stop_ignoring_errors (dpyinfo); 11607 x_stop_ignoring_errors (dpyinfo);
@@ -11468,7 +11624,7 @@ x_frame_unhighlight (struct frame *f)
11468 11624
11469 block_input (); 11625 block_input ();
11470 /* Same as above for XSetWindowBorder (bug#9310). */ 11626 /* Same as above for XSetWindowBorder (bug#9310). */
11471 x_ignore_errors_for_next_request (dpyinfo); 11627 x_ignore_errors_for_next_request (dpyinfo, 0);
11472 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 11628 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11473 f->output_data.x->border_tile); 11629 f->output_data.x->border_tile);
11474 x_stop_ignoring_errors (dpyinfo); 11630 x_stop_ignoring_errors (dpyinfo);
@@ -11532,7 +11688,7 @@ x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
11532 x_frame_rehighlight (dpyinfo); 11688 x_frame_rehighlight (dpyinfo);
11533} 11689}
11534 11690
11535#ifdef HAVE_XFIXES 11691#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11536 11692
11537/* True if the display in DPYINFO supports a version of Xfixes 11693/* True if the display in DPYINFO supports a version of Xfixes
11538 sufficient for pointer blanking. */ 11694 sufficient for pointer blanking. */
@@ -11544,11 +11700,12 @@ x_fixes_pointer_blanking_supported (struct x_display_info *dpyinfo)
11544 && dpyinfo->xfixes_major >= 4); 11700 && dpyinfo->xfixes_major >= 4);
11545} 11701}
11546 11702
11547#endif /* HAVE_XFIXES */ 11703#endif /* HAVE_XFIXES && XFIXES_VERSION >= 40000 */
11548 11704
11549/* Toggle mouse pointer visibility on frame F using the XFixes 11705/* Toggle mouse pointer visibility on frame F using the XFixes
11550 extension. */ 11706 extension. */
11551#ifdef HAVE_XFIXES 11707#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11708
11552static void 11709static void
11553xfixes_toggle_visible_pointer (struct frame *f, bool invisible) 11710xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
11554 11711
@@ -11559,6 +11716,7 @@ xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
11559 XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 11716 XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
11560 f->pointer_invisible = invisible; 11717 f->pointer_invisible = invisible;
11561} 11718}
11719
11562#endif /* HAVE_XFIXES */ 11720#endif /* HAVE_XFIXES */
11563 11721
11564/* Create invisible cursor on the X display referred by DPYINFO. */ 11722/* Create invisible cursor on the X display referred by DPYINFO. */
@@ -11607,7 +11765,7 @@ x_toggle_visible_pointer (struct frame *f, bool invisible)
11607 if (dpyinfo->invisible_cursor == None) 11765 if (dpyinfo->invisible_cursor == None)
11608 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo); 11766 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
11609 11767
11610#ifndef HAVE_XFIXES 11768#if !defined HAVE_XFIXES || XFIXES_VERSION < 40000
11611 if (dpyinfo->invisible_cursor == None) 11769 if (dpyinfo->invisible_cursor == None)
11612 invisible = false; 11770 invisible = false;
11613#else 11771#else
@@ -11640,7 +11798,7 @@ static void
11640XTtoggle_invisible_pointer (struct frame *f, bool invisible) 11798XTtoggle_invisible_pointer (struct frame *f, bool invisible)
11641{ 11799{
11642 block_input (); 11800 block_input ();
11643#ifdef HAVE_XFIXES 11801#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
11644 if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking 11802 if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking
11645 && x_fixes_pointer_blanking_supported (FRAME_DISPLAY_INFO (f))) 11803 && x_fixes_pointer_blanking_supported (FRAME_DISPLAY_INFO (f)))
11646 xfixes_toggle_visible_pointer (f, invisible); 11804 xfixes_toggle_visible_pointer (f, invisible);
@@ -12229,6 +12387,13 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
12229 struct xi_device_t *device; 12387 struct xi_device_t *device;
12230#endif 12388#endif
12231 12389
12390 if (FRAME_DISPLAY_INFO (f)->untrusted)
12391 /* Untrusted clients cannot send messages to trusted clients or
12392 read the window tree, so drag and drop will likely not work at
12393 all. */
12394 error ("Drag-and-drop is not possible when the client is"
12395 " not trusted by the X server.");
12396
12232 base = SPECPDL_INDEX (); 12397 base = SPECPDL_INDEX ();
12233 12398
12234 /* Bind this here to avoid juggling bindings and SAFE_FREE in 12399 /* Bind this here to avoid juggling bindings and SAFE_FREE in
@@ -15000,9 +15165,7 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
15000 XClientMessageEvent *ev = &event.xclient; 15165 XClientMessageEvent *ev = &event.xclient;
15001 struct window *w = XWINDOW (window); 15166 struct window *w = XWINDOW (window);
15002 struct frame *f = XFRAME (w->frame); 15167 struct frame *f = XFRAME (w->frame);
15003 intptr_t iw = (intptr_t) w;
15004 verify (INTPTR_WIDTH <= 64); 15168 verify (INTPTR_WIDTH <= 64);
15005 int sign_shift = INTPTR_WIDTH - 32;
15006 15169
15007 /* Don't do anything if too many scroll bar events have been 15170 /* Don't do anything if too many scroll bar events have been
15008 sent but not received. */ 15171 sent but not received. */
@@ -15019,15 +15182,11 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
15019 ev->window = FRAME_X_WINDOW (f); 15182 ev->window = FRAME_X_WINDOW (f);
15020 ev->format = 32; 15183 ev->format = 32;
15021 15184
15022 /* A 32-bit X client can pass a window pointer through the X server 15185 /* These messages formerly contained a pointer to the window, but
15023 as-is. 15186 now that information is kept internally. The following two
15024 15187 fields are thus zero. */
15025 A 64-bit client is in trouble because a pointer does not fit in 15188 ev->data.l[0] = 0;
15026 the 32 bits given for ClientMessage data and will be truncated by 15189 ev->data.l[1] = 0;
15027 Xlib. So use two slots and hope that X12 will resolve such
15028 issues someday. */
15029 ev->data.l[0] = iw >> 31 >> 1;
15030 ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
15031 ev->data.l[2] = part; 15190 ev->data.l[2] = part;
15032 ev->data.l[3] = portion; 15191 ev->data.l[3] = portion;
15033 ev->data.l[4] = whole; 15192 ev->data.l[4] = whole;
@@ -18458,7 +18617,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
18458 x_dnd_waiting_for_status_window = None; 18617 x_dnd_waiting_for_status_window = None;
18459 else 18618 else
18460 { 18619 {
18461 x_ignore_errors_for_next_request (dpyinfo); 18620 x_ignore_errors_for_next_request (dpyinfo, 0);
18462 XSendEvent (dpyinfo->display, target, 18621 XSendEvent (dpyinfo->display, target,
18463 False, NoEventMask, 18622 False, NoEventMask,
18464 &x_dnd_pending_send_position); 18623 &x_dnd_pending_send_position);
@@ -18572,6 +18731,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
18572 } 18731 }
18573 } 18732 }
18574 18733
18734 if (event->xclient.message_type == dpyinfo->Xatom_EMACS_TMP
18735 && event->xclient.format == 8)
18736 {
18737 /* This is actually an hourglass message. Set whether or
18738 not events from here on have the hourglass enabled. */
18739
18740 if (any)
18741 FRAME_X_OUTPUT (any)->hourglass_p = event->xclient.data.b[0];
18742 }
18743
18575 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols 18744 if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
18576 && event->xclient.format == 32) 18745 && event->xclient.format == 32)
18577 { 18746 {
@@ -19160,7 +19329,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19160 = xcb_get_property (dpyinfo->xcb_connection, 0, 19329 = xcb_get_property (dpyinfo->xcb_connection, 0,
19161 (xcb_window_t) FRAME_OUTER_WINDOW (f), 19330 (xcb_window_t) FRAME_OUTER_WINDOW (f),
19162 (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity, 19331 (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity,
19163 XCB_ATOM_CARDINAL, 0, 1); 19332 XA_CARDINAL, 0, 1);
19164 opacity_reply 19333 opacity_reply
19165 = xcb_get_property_reply (dpyinfo->xcb_connection, 19334 = xcb_get_property_reply (dpyinfo->xcb_connection,
19166 opacity_cookie, &error); 19335 opacity_cookie, &error);
@@ -19169,9 +19338,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19169 free (error), rc = false; 19338 free (error), rc = false;
19170 else 19339 else
19171 rc = (opacity_reply->format == 32 19340 rc = (opacity_reply->format == 32
19172 && (opacity_reply->type == XCB_ATOM_CARDINAL 19341 && (opacity_reply->type == XA_CARDINAL
19173 || opacity_reply->type == XCB_ATOM_ATOM 19342 || opacity_reply->type == XA_ATOM
19174 || opacity_reply->type == XCB_ATOM_WINDOW) 19343 || opacity_reply->type == XA_WINDOW)
19175 && (xcb_get_property_value_length (opacity_reply) >= 4)); 19344 && (xcb_get_property_value_length (opacity_reply) >= 4));
19176 19345
19177 if (rc) 19346 if (rc)
@@ -21317,7 +21486,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21317 21486
21318 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf))) 21487 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
21319 { 21488 {
21320 x_ignore_errors_for_next_request (dpyinfo); 21489 x_ignore_errors_for_next_request (dpyinfo, 0);
21321 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 21490 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
21322 RevertToParent, event->xbutton.time); 21491 RevertToParent, event->xbutton.time);
21323 x_stop_ignoring_errors (dpyinfo); 21492 x_stop_ignoring_errors (dpyinfo);
@@ -21430,7 +21599,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21430 if (!NILP (tab_bar_arg)) 21599 if (!NILP (tab_bar_arg))
21431 inev.ie.arg = tab_bar_arg; 21600 inev.ie.arg = tab_bar_arg;
21432 } 21601 }
21433 if (FRAME_X_EMBEDDED_P (f)) 21602
21603 if (FRAME_X_EMBEDDED_P (f)
21604 && !FRAME_NO_ACCEPT_FOCUS (f))
21434 xembed_send_message (f, event->xbutton.time, 21605 xembed_send_message (f, event->xbutton.time,
21435 XEMBED_REQUEST_FOCUS, 0, 0, 0); 21606 XEMBED_REQUEST_FOCUS, 0, 0, 0);
21436 } 21607 }
@@ -23013,7 +23184,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23013 /* This can generate XI_BadDevice if the 23184 /* This can generate XI_BadDevice if the
23014 device's attachment was destroyed 23185 device's attachment was destroyed
23015 server-side. */ 23186 server-side. */
23016 x_ignore_errors_for_next_request (dpyinfo); 23187 x_ignore_errors_for_next_request (dpyinfo, 0);
23017 XISetFocus (dpyinfo->display, device->attachment, 23188 XISetFocus (dpyinfo->display, device->attachment,
23018 /* Note that the input extension 23189 /* Note that the input extension
23019 only supports RevertToParent-type 23190 only supports RevertToParent-type
@@ -23026,7 +23197,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23026 events to handle focus. Errors are still 23197 events to handle focus. Errors are still
23027 caught here in case the window is not 23198 caught here in case the window is not
23028 viewable. */ 23199 viewable. */
23029 x_ignore_errors_for_next_request (dpyinfo); 23200 x_ignore_errors_for_next_request (dpyinfo, 0);
23030 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 23201 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
23031 RevertToParent, xev->time); 23202 RevertToParent, xev->time);
23032 x_stop_ignoring_errors (dpyinfo); 23203 x_stop_ignoring_errors (dpyinfo);
@@ -23198,7 +23369,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23198 if (!NILP (tab_bar_arg)) 23369 if (!NILP (tab_bar_arg))
23199 inev.ie.arg = tab_bar_arg; 23370 inev.ie.arg = tab_bar_arg;
23200 } 23371 }
23201 if (FRAME_X_EMBEDDED_P (f)) 23372
23373 if (FRAME_X_EMBEDDED_P (f)
23374 && !FRAME_NO_ACCEPT_FOCUS (f))
23202 xembed_send_message (f, xev->time, 23375 xembed_send_message (f, xev->time,
23203 XEMBED_REQUEST_FOCUS, 0, 0, 0); 23376 XEMBED_REQUEST_FOCUS, 0, 0, 0);
23204 } 23377 }
@@ -24033,7 +24206,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
24033#ifndef HAVE_GTK3 24206#ifndef HAVE_GTK3
24034 else if (x_input_grab_touch_events) 24207 else if (x_input_grab_touch_events)
24035 { 24208 {
24036 x_ignore_errors_for_next_request (dpyinfo); 24209 x_ignore_errors_for_next_request (dpyinfo, 0);
24037 XIAllowTouchEvents (dpyinfo->display, xev->deviceid, 24210 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
24038 xev->detail, xev->event, XIRejectTouch); 24211 xev->detail, xev->event, XIRejectTouch);
24039 x_stop_ignoring_errors (dpyinfo); 24212 x_stop_ignoring_errors (dpyinfo);
@@ -25461,14 +25634,38 @@ x_clean_failable_requests (struct x_display_info *dpyinfo)
25461 + (last - first)); 25634 + (last - first));
25462} 25635}
25463 25636
25637/* Protect a section of X requests: ignore errors generated by X
25638 requests made from now until `x_stop_ignoring_errors'. Each call
25639 must be paired with a call to `x_stop_ignoring_errors', and
25640 recursive calls inside the protected section are not allowed.
25641
25642 The advantage over x_catch_errors followed by
25643 x_uncatch_errors_after_check is that this function does not sync to
25644 catch errors if requests were made. It should be used instead of
25645 those two functions for catching errors around requests that do not
25646 require a reply.
25647
25648 As a special feature intended to support xselect.c,
25649 SELECTION_SERIAL may be an arbitrary number greater than zero: when
25650 that is the case, x_select_handle_selection_error is called with
25651 the specified number to delete the selection request that
25652 encountered the error. */
25653
25464void 25654void
25465x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) 25655x_ignore_errors_for_next_request (struct x_display_info *dpyinfo,
25656 unsigned int selection_serial)
25466{ 25657{
25467 struct x_failable_request *request, *max; 25658 struct x_failable_request *request, *max;
25468 unsigned long next_request; 25659 unsigned long next_request;
25469#ifdef HAVE_GTK3 25660#ifdef HAVE_GTK3
25470 GdkDisplay *gdpy; 25661 GdkDisplay *gdpy;
25662#endif
25471 25663
25664 /* This code is not reentrant, so be sure nothing calls it
25665 recursively in response to input. */
25666 block_input ();
25667
25668#ifdef HAVE_GTK3
25472 /* GTK 3 tends to override our own error handler inside certain 25669 /* GTK 3 tends to override our own error handler inside certain
25473 callbacks, which this can be called from. Instead of trying to 25670 callbacks, which this can be called from. Instead of trying to
25474 restore our own, add a trap for the following requests with 25671 restore our own, add a trap for the following requests with
@@ -25510,6 +25707,7 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
25510 25707
25511 request->start = next_request; 25708 request->start = next_request;
25512 request->end = 0; 25709 request->end = 0;
25710 request->selection_serial = selection_serial;
25513 25711
25514 dpyinfo->next_failable_request++; 25712 dpyinfo->next_failable_request++;
25515} 25713}
@@ -25537,6 +25735,8 @@ x_stop_ignoring_errors (struct x_display_info *dpyinfo)
25537 if (gdpy) 25735 if (gdpy)
25538 gdk_x11_display_error_trap_pop_ignored (gdpy); 25736 gdk_x11_display_error_trap_pop_ignored (gdpy);
25539#endif 25737#endif
25738
25739 unblock_input ();
25540} 25740}
25541 25741
25542/* Undo the last x_catch_errors call. 25742/* Undo the last x_catch_errors call.
@@ -25929,9 +26129,11 @@ For details, see etc/PROBLEMS.\n",
25929 if (!ioerror && dpyinfo) 26129 if (!ioerror && dpyinfo)
25930 { 26130 {
25931 /* Dump the list of error handlers for debugging 26131 /* Dump the list of error handlers for debugging
25932 purposes. */ 26132 purposes if the list exists. */
25933 26133
25934 fprintf (stderr, "X error handlers currently installed:\n"); 26134 if ((dpyinfo->failable_requests
26135 != dpyinfo->next_failable_request) || x_error_message)
26136 fprintf (stderr, "X error handlers currently installed:\n");
25935 26137
25936 for (failable = dpyinfo->failable_requests; 26138 for (failable = dpyinfo->failable_requests;
25937 failable < dpyinfo->next_failable_request; 26139 failable < dpyinfo->next_failable_request;
@@ -26020,6 +26222,12 @@ x_error_handler (Display *display, XErrorEvent *event)
26020 + (last - fail)); 26222 + (last - fail));
26021 } 26223 }
26022 26224
26225 /* If a selection transfer is the cause of this error,
26226 remove the selection transfer now. */
26227 if (fail->selection_serial)
26228 x_handle_selection_error (fail->selection_serial,
26229 event);
26230
26023 return 0; 26231 return 0;
26024 } 26232 }
26025 } 26233 }
@@ -26572,38 +26780,43 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
26572 modified_left, modified_top); 26780 modified_left, modified_top);
26573#endif 26781#endif
26574 26782
26575 /* 'x_sync_with_move' is too costly for dragging child frames. */ 26783 /* The following code is too slow over a latent network
26576 if (!FRAME_PARENT_FRAME (f) 26784 connection. */
26577 /* If no window manager exists, just calling XSync will be 26785 if (NILP (Vx_lax_frame_positioning))
26578 sufficient to ensure that the window geometry has been 26786 {
26579 updated. */ 26787 /* 'x_sync_with_move' is too costly for dragging child frames. */
26580 && NILP (Vx_no_window_manager)) 26788 if (!FRAME_PARENT_FRAME (f)
26581 { 26789 /* If no window manager exists, just calling XSync will be
26582 x_sync_with_move (f, f->left_pos, f->top_pos, 26790 sufficient to ensure that the window geometry has been
26583 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN); 26791 updated. */
26584 26792 && NILP (Vx_no_window_manager))
26585 /* change_gravity is non-zero when this function is called from Lisp to 26793 {
26586 programmatically move a frame. In that case, we call 26794 x_sync_with_move (f, f->left_pos, f->top_pos,
26587 x_check_expected_move to discover if we have a "Type A" or "Type B" 26795 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
26588 window manager, and, for a "Type A" window manager, adjust the position 26796
26589 of the frame. 26797 /* change_gravity is non-zero when this function is called from Lisp to
26590 26798 programmatically move a frame. In that case, we call
26591 We call x_check_expected_move if a programmatic move occurred, and 26799 x_check_expected_move to discover if we have a "Type A" or "Type B"
26592 either the window manager type (A/B) is unknown or it is Type A but we 26800 window manager, and, for a "Type A" window manager, adjust the position
26593 need to compute the top/left offset adjustment for this frame. */ 26801 of the frame.
26594 26802
26595 if (change_gravity != 0 26803 We call x_check_expected_move if a programmatic move occurred, and
26596 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN 26804 either the window manager type (A/B) is unknown or it is Type A but we
26597 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A 26805 need to compute the top/left offset adjustment for this frame. */
26598 && (FRAME_X_OUTPUT (f)->move_offset_left == 0 26806
26599 && FRAME_X_OUTPUT (f)->move_offset_top == 0)))) 26807 if (change_gravity != 0
26600 x_check_expected_move (f, modified_left, modified_top); 26808 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
26601 } 26809 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
26602 /* Instead, just wait for the last ConfigureWindow request to 26810 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
26603 complete. No window manager is involved when moving child 26811 && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
26604 frames. */ 26812 x_check_expected_move (f, modified_left, modified_top);
26605 else 26813 }
26606 XSync (FRAME_X_DISPLAY (f), False); 26814 /* Instead, just wait for the last ConfigureWindow request to
26815 complete. No window manager is involved when moving child
26816 frames. */
26817 else
26818 XSync (FRAME_X_DISPLAY (f), False);
26819 }
26607 26820
26608 unblock_input (); 26821 unblock_input ();
26609} 26822}
@@ -26663,6 +26876,12 @@ x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
26663 if (!NILP (Vx_no_window_manager)) 26876 if (!NILP (Vx_no_window_manager))
26664 return false; 26877 return false;
26665 26878
26879 /* If the window system says Emacs is untrusted, there will be no
26880 way to send any information to the window manager, making any
26881 hints useless. */
26882 if (dpyinfo->untrusted)
26883 return false;
26884
26666 block_input (); 26885 block_input ();
26667 26886
26668 x_catch_errors (dpy); 26887 x_catch_errors (dpy);
@@ -26713,13 +26932,14 @@ x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
26713 26932
26714 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy)) 26933 if (rc != Success || actual_type != XA_ATOM || x_had_errors_p (dpy))
26715 { 26934 {
26716 if (tmp_data) XFree (tmp_data); 26935 if (tmp_data)
26936 XFree (tmp_data);
26717 x_uncatch_errors (); 26937 x_uncatch_errors ();
26718 unblock_input (); 26938 unblock_input ();
26719 return false; 26939 return false;
26720 } 26940 }
26721 26941
26722 dpyinfo->net_supported_atoms = (Atom *)tmp_data; 26942 dpyinfo->net_supported_atoms = (Atom *) tmp_data;
26723 dpyinfo->nr_net_supported_atoms = actual_size; 26943 dpyinfo->nr_net_supported_atoms = actual_size;
26724 dpyinfo->net_supported_window = wmcheck_window; 26944 dpyinfo->net_supported_window = wmcheck_window;
26725 } 26945 }
@@ -27132,13 +27352,12 @@ do_ewmh_fullscreen (struct frame *f)
27132static void 27352static void
27133XTfullscreen_hook (struct frame *f) 27353XTfullscreen_hook (struct frame *f)
27134{ 27354{
27135 if (FRAME_VISIBLE_P (f)) 27355 if (!FRAME_VISIBLE_P (f))
27136 { 27356 return;
27137 block_input (); 27357
27138 x_check_fullscreen (f); 27358 block_input ();
27139 x_sync (f); 27359 x_check_fullscreen (f);
27140 unblock_input (); 27360 unblock_input ();
27141 }
27142} 27361}
27143 27362
27144 27363
@@ -27232,10 +27451,7 @@ x_check_fullscreen (struct frame *f)
27232 if (FRAME_VISIBLE_P (f)) 27451 if (FRAME_VISIBLE_P (f))
27233 x_wait_for_event (f, ConfigureNotify); 27452 x_wait_for_event (f, ConfigureNotify);
27234 else 27453 else
27235 { 27454 change_frame_size (f, width, height, false, true, false);
27236 change_frame_size (f, width, height, false, true, false);
27237 x_sync (f);
27238 }
27239 } 27455 }
27240 27456
27241 /* `x_net_wm_state' might have reset the fullscreen frame parameter, 27457 /* `x_net_wm_state' might have reset the fullscreen frame parameter,
@@ -27409,6 +27625,12 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
27409 we have to make sure to do it here. */ 27625 we have to make sure to do it here. */
27410 SET_FRAME_GARBAGED (f); 27626 SET_FRAME_GARBAGED (f);
27411 27627
27628 /* The following code is too slow over a latent network
27629 connection, so skip it when the user says so. */
27630
27631 if (!NILP (Vx_lax_frame_positioning))
27632 return;
27633
27412 /* Now, strictly speaking, we can't be sure that this is accurate, 27634 /* Now, strictly speaking, we can't be sure that this is accurate,
27413 but the window manager will get around to dealing with the size 27635 but the window manager will get around to dealing with the size
27414 change request eventually, and we'll hear how it went when the 27636 change request eventually, and we'll hear how it went when the
@@ -27449,8 +27671,6 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
27449 adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), 27671 adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width),
27450 FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), 27672 FRAME_PIXEL_TO_TEXT_HEIGHT (f, height),
27451 5, 0, Qx_set_window_size_1); 27673 5, 0, Qx_set_window_size_1);
27452
27453 x_sync (f);
27454 } 27674 }
27455} 27675}
27456 27676
@@ -27504,7 +27724,7 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
27504 && deviceid != -1) 27724 && deviceid != -1)
27505 { 27725 {
27506 block_input (); 27726 block_input ();
27507 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f)); 27727 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
27508 XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None, 27728 XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
27509 FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y); 27729 FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
27510 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f)); 27730 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
@@ -27801,7 +28021,7 @@ x_set_input_focus (struct x_display_info *dpyinfo, Window window,
27801 { 28021 {
27802 eassert (device->use == XIMasterPointer); 28022 eassert (device->use == XIMasterPointer);
27803 28023
27804 x_ignore_errors_for_next_request (dpyinfo); 28024 x_ignore_errors_for_next_request (dpyinfo, 0);
27805 XISetFocus (dpyinfo->display, device->attachment, 28025 XISetFocus (dpyinfo->display, device->attachment,
27806 /* Note that the input extension 28026 /* Note that the input extension
27807 only supports RevertToParent-type 28027 only supports RevertToParent-type
@@ -27816,7 +28036,7 @@ x_set_input_focus (struct x_display_info *dpyinfo, Window window,
27816 28036
27817 /* Otherwise, use the pointer device that the X server says is the 28037 /* Otherwise, use the pointer device that the X server says is the
27818 client pointer. */ 28038 client pointer. */
27819 x_ignore_errors_for_next_request (dpyinfo); 28039 x_ignore_errors_for_next_request (dpyinfo, 0);
27820 XSetInputFocus (dpyinfo->display, window, RevertToParent, time); 28040 XSetInputFocus (dpyinfo->display, window, RevertToParent, time);
27821 x_stop_ignoring_errors (dpyinfo); 28041 x_stop_ignoring_errors (dpyinfo);
27822} 28042}
@@ -27838,6 +28058,15 @@ x_focus_frame (struct frame *f, bool noactivate)
27838 28058
27839 dpyinfo = FRAME_DISPLAY_INFO (f); 28059 dpyinfo = FRAME_DISPLAY_INFO (f);
27840 28060
28061 if (dpyinfo->untrusted)
28062 /* The X server ignores all input focus related requests from
28063 untrusted clients. */
28064 return;
28065
28066 /* The code below is not reentrant wrt to dpyinfo->x_focus_frame and
28067 friends being set. */
28068 block_input ();
28069
27841 if (FRAME_X_EMBEDDED_P (f)) 28070 if (FRAME_X_EMBEDDED_P (f))
27842 /* For Xembedded frames, normally the embedder forwards key 28071 /* For Xembedded frames, normally the embedder forwards key
27843 events. See XEmbed Protocol Specification at 28072 events. See XEmbed Protocol Specification at
@@ -27866,7 +28095,7 @@ x_focus_frame (struct frame *f, bool noactivate)
27866 the current workspace, and mapping it, etc, before moving 28095 the current workspace, and mapping it, etc, before moving
27867 input focus to the frame. */ 28096 input focus to the frame. */
27868 x_ewmh_activate_frame (f); 28097 x_ewmh_activate_frame (f);
27869 return; 28098 goto out;
27870 } 28099 }
27871 28100
27872 if (NILP (Vx_no_window_manager)) 28101 if (NILP (Vx_no_window_manager))
@@ -27900,6 +28129,9 @@ x_focus_frame (struct frame *f, bool noactivate)
27900 matter. */ 28129 matter. */
27901 CurrentTime); 28130 CurrentTime);
27902 } 28131 }
28132
28133 out:
28134 unblock_input ();
27903} 28135}
27904 28136
27905 28137
@@ -27946,7 +28178,7 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
27946 but I don't understand why: there is no way for clients to 28178 but I don't understand why: there is no way for clients to
27947 survive the death of the parent anyway. */ 28179 survive the death of the parent anyway. */
27948 28180
27949 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f)); 28181 x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
27950 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc, 28182 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
27951 False, NoEventMask, &event); 28183 False, NoEventMask, &event);
27952 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f)); 28184 x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
@@ -28097,6 +28329,7 @@ x_make_frame_visible (struct frame *f)
28097 && !FRAME_ICONIFIED_P (f) 28329 && !FRAME_ICONIFIED_P (f)
28098 && !FRAME_X_EMBEDDED_P (f) 28330 && !FRAME_X_EMBEDDED_P (f)
28099 && !FRAME_PARENT_FRAME (f) 28331 && !FRAME_PARENT_FRAME (f)
28332 && NILP (Vx_lax_frame_positioning)
28100 && f->win_gravity == NorthWestGravity 28333 && f->win_gravity == NorthWestGravity
28101 && previously_visible) 28334 && previously_visible)
28102 { 28335 {
@@ -28125,7 +28358,8 @@ x_make_frame_visible (struct frame *f)
28125 } 28358 }
28126 28359
28127 /* Try to wait for a MapNotify event (that is what tells us when a 28360 /* Try to wait for a MapNotify event (that is what tells us when a
28128 frame becomes visible). */ 28361 frame becomes visible). Unless `x-lax-frame-positioning' is
28362 non-nil: there, that is a little slow. */
28129 28363
28130#ifdef CYGWIN 28364#ifdef CYGWIN
28131 /* On Cygwin, which uses input polling, we need to force input to 28365 /* On Cygwin, which uses input polling, we need to force input to
@@ -28143,7 +28377,8 @@ x_make_frame_visible (struct frame *f)
28143 poll_suppress_count = old_poll_suppress_count; 28377 poll_suppress_count = old_poll_suppress_count;
28144#endif 28378#endif
28145 28379
28146 if (!FRAME_VISIBLE_P (f)) 28380 if (!FRAME_VISIBLE_P (f)
28381 && NILP (Vx_lax_frame_positioning))
28147 { 28382 {
28148 if (CONSP (frame_size_history)) 28383 if (CONSP (frame_size_history))
28149 frame_size_history_plain 28384 frame_size_history_plain
@@ -28200,7 +28435,7 @@ x_make_frame_invisible (struct frame *f)
28200 error ("Can't notify window manager of window withdrawal"); 28435 error ("Can't notify window manager of window withdrawal");
28201 } 28436 }
28202 28437
28203 x_sync (f); 28438 XSync (FRAME_X_DISPLAY (f), False);
28204 28439
28205 /* We can't distinguish this from iconification 28440 /* We can't distinguish this from iconification
28206 just by the event that we get from the server. 28441 just by the event that we get from the server.
@@ -28798,6 +29033,53 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
28798 return value; 29033 return value;
28799} 29034}
28800 29035
29036/* Intern an array of atoms, and do so quickly, avoiding extraneous
29037 roundtrips to the X server.
29038
29039 Avoid sending atoms that have already been found to the X server.
29040 This cannot do anything that will end up triggering garbage
29041 collection. */
29042
29043void
29044x_intern_atoms (struct x_display_info *dpyinfo, char **names, int count,
29045 Atom *atoms_return)
29046{
29047 int i, j, indices[256];
29048 char *new_names[256];
29049 Atom results[256], candidate;
29050
29051 if (count > 256)
29052 /* Atoms array too big to inspect reasonably, just send it to the
29053 server and back. */
29054 XInternAtoms (dpyinfo->display, new_names, count, False, atoms_return);
29055 else
29056 {
29057 for (i = 0, j = 0; i < count; ++i)
29058 {
29059 candidate = x_intern_cached_atom (dpyinfo, names[i],
29060 true);
29061
29062 if (candidate)
29063 atoms_return[i] = candidate;
29064 else
29065 {
29066 indices[j++] = i;
29067 new_names[j - 1] = names[i];
29068 }
29069 }
29070
29071 if (!j)
29072 return;
29073
29074 /* Now, get the results back from the X server. */
29075 XInternAtoms (dpyinfo->display, new_names, j, False,
29076 results);
29077
29078 for (i = 0; i < j; ++i)
29079 atoms_return[indices[i]] = results[i];
29080 }
29081}
29082
28801#ifndef USE_GTK 29083#ifndef USE_GTK
28802 29084
28803/* Set up XEmbed for F, and change its save set to handle the parent 29085/* Set up XEmbed for F, and change its save set to handle the parent
@@ -29346,6 +29628,7 @@ struct x_display_info *
29346x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) 29628x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29347{ 29629{
29348 Display *dpy; 29630 Display *dpy;
29631 XKeyboardState keyboard_state;
29349 struct terminal *terminal; 29632 struct terminal *terminal;
29350 struct x_display_info *dpyinfo; 29633 struct x_display_info *dpyinfo;
29351 XrmDatabase xrdb; 29634 XrmDatabase xrdb;
@@ -29565,6 +29848,32 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29565 dpyinfo = xzalloc (sizeof *dpyinfo); 29848 dpyinfo = xzalloc (sizeof *dpyinfo);
29566 terminal = x_create_terminal (dpyinfo); 29849 terminal = x_create_terminal (dpyinfo);
29567 29850
29851 if (!NILP (Vx_detect_server_trust))
29852 {
29853 /* Detect whether or not the X server trusts this client, which
29854 is done by making a SetKeyboardControl request and checking
29855 for an Access error. */
29856 XGrabServer (dpy);
29857 XGetKeyboardControl (dpy, &keyboard_state);
29858
29859 x_catch_errors (dpy);
29860
29861 /* At this point, the display is not on x_display_list, so
29862 x_uncatch_errors won't sync. However, that's okay because
29863 x_had_errors_p will. */
29864
29865 if (keyboard_state.global_auto_repeat
29866 == AutoRepeatModeOn)
29867 XAutoRepeatOn (dpy);
29868 else
29869 XAutoRepeatOff (dpy);
29870
29871 if (x_had_errors_p (dpy))
29872 dpyinfo->untrusted = true;
29873 x_uncatch_errors_after_check ();
29874 XUngrabServer (dpy);
29875 }
29876
29568 dpyinfo->next_failable_request = dpyinfo->failable_requests; 29877 dpyinfo->next_failable_request = dpyinfo->failable_requests;
29569 29878
29570 { 29879 {
@@ -29585,13 +29894,17 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
29585 { 29894 {
29586 char *vendor = ServerVendor (dpy); 29895 char *vendor = ServerVendor (dpy);
29587 29896
29588 /* Temporarily hide the partially initialized terminal. */ 29897 /* Temporarily hide the partially initialized terminal.
29898 Use safe_call so that if a signal happens, a partially
29899 initialized display (and display connection) is not
29900 kept around. */
29589 terminal_list = terminal->next_terminal; 29901 terminal_list = terminal->next_terminal;
29590 unblock_input (); 29902 unblock_input ();
29591 kset_system_key_alist 29903 kset_system_key_alist (terminal->kboard,
29592 (terminal->kboard, 29904 safe_call1 (Qvendor_specific_keysyms,
29593 call1 (Qvendor_specific_keysyms, 29905 (vendor
29594 vendor ? build_string (vendor) : empty_unibyte_string)); 29906 ? build_string (vendor)
29907 : empty_unibyte_string)));
29595 block_input (); 29908 block_input ();
29596 terminal->next_terminal = terminal_list; 29909 terminal->next_terminal = terminal_list;
29597 terminal_list = terminal; 29910 terminal_list = terminal;
@@ -30209,7 +30522,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
30209 1, 0, 1); 30522 1, 0, 1);
30210 30523
30211 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo); 30524 dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
30212#ifdef HAVE_XFIXES 30525#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
30213 dpyinfo->fixes_pointer_blanking = egetenv ("EMACS_XFIXES"); 30526 dpyinfo->fixes_pointer_blanking = egetenv ("EMACS_XFIXES");
30214#endif 30527#endif
30215 30528
@@ -30537,8 +30850,13 @@ x_delete_display (struct x_display_info *dpyinfo)
30537 last = ie; 30850 last = ie;
30538 } 30851 }
30539 30852
30853 /* Delete selection requests bound for dpyinfo from the keyboard
30854 buffer. */
30540 x_delete_selection_requests (dpyinfo); 30855 x_delete_selection_requests (dpyinfo);
30541 30856
30857 /* And remove any outstanding selection transfers. */
30858 x_remove_selection_transfers (dpyinfo);
30859
30542 if (next_noop_dpyinfo == dpyinfo) 30860 if (next_noop_dpyinfo == dpyinfo)
30543 next_noop_dpyinfo = dpyinfo->next; 30861 next_noop_dpyinfo = dpyinfo->next;
30544 30862
@@ -30568,6 +30886,9 @@ x_delete_display (struct x_display_info *dpyinfo)
30568 } 30886 }
30569 } 30887 }
30570 30888
30889 if (dpyinfo->net_supported_atoms)
30890 XFree (dpyinfo->net_supported_atoms);
30891
30571 xfree (dpyinfo->color_names); 30892 xfree (dpyinfo->color_names);
30572 xfree (dpyinfo->color_names_length); 30893 xfree (dpyinfo->color_names_length);
30573 xfree (dpyinfo->x_id_name); 30894 xfree (dpyinfo->x_id_name);
@@ -30679,7 +31000,11 @@ static struct redisplay_interface x_redisplay_interface =
30679void 31000void
30680x_delete_terminal (struct terminal *terminal) 31001x_delete_terminal (struct terminal *terminal)
30681{ 31002{
30682 struct x_display_info *dpyinfo = terminal->display_info.x; 31003 struct x_display_info *dpyinfo;
31004 struct frame *f;
31005 Lisp_Object tail, frame;
31006
31007 dpyinfo = terminal->display_info.x;
30683 31008
30684 /* Protect against recursive calls. delete_frame in 31009 /* Protect against recursive calls. delete_frame in
30685 delete_terminal calls us back when it deletes our last frame. */ 31010 delete_terminal calls us back when it deletes our last frame. */
@@ -30687,6 +31012,19 @@ x_delete_terminal (struct terminal *terminal)
30687 return; 31012 return;
30688 31013
30689 block_input (); 31014 block_input ();
31015
31016 /* Delete all remaining frames on the display that is going away.
31017 Otherwise, font backends assume the display is still up, and
31018 xftfont_end_for_frame crashes. */
31019 FOR_EACH_FRAME (tail, frame)
31020 {
31021 f = XFRAME (frame);
31022
31023 if (FRAME_LIVE_P (f) && f->terminal == terminal)
31024 /* Pass Qnoelisp rather than Qt. */
31025 delete_frame (frame, Qnoelisp);
31026 }
31027
30690#ifdef HAVE_X_I18N 31028#ifdef HAVE_X_I18N
30691 /* We must close our connection to the XIM server before closing the 31029 /* We must close our connection to the XIM server before closing the
30692 X display. */ 31030 X display. */
@@ -30700,6 +31038,10 @@ x_delete_terminal (struct terminal *terminal)
30700 image_destroy_all_bitmaps (dpyinfo); 31038 image_destroy_all_bitmaps (dpyinfo);
30701 XSetCloseDownMode (dpyinfo->display, DestroyAll); 31039 XSetCloseDownMode (dpyinfo->display, DestroyAll);
30702 31040
31041 /* Delete the scratch cursor GC, should it exist. */
31042 if (dpyinfo->scratch_cursor_gc)
31043 XFreeGC (dpyinfo->display, dpyinfo->scratch_cursor_gc);
31044
30703 /* Get rid of any drag-and-drop operation that might be in 31045 /* Get rid of any drag-and-drop operation that might be in
30704 progress as well. */ 31046 progress as well. */
30705 if ((x_dnd_in_progress || x_dnd_waiting_for_finish) 31047 if ((x_dnd_in_progress || x_dnd_waiting_for_finish)
@@ -31020,7 +31362,7 @@ x_catch_errors_for_lisp (struct x_display_info *dpyinfo)
31020 if (!x_fast_protocol_requests) 31362 if (!x_fast_protocol_requests)
31021 x_catch_errors (dpyinfo->display); 31363 x_catch_errors (dpyinfo->display);
31022 else 31364 else
31023 x_ignore_errors_for_next_request (dpyinfo); 31365 x_ignore_errors_for_next_request (dpyinfo, 0);
31024} 31366}
31025 31367
31026void 31368void
@@ -31229,6 +31571,8 @@ syms_of_xterm (void)
31229 DEFSYM (Qnow, "now"); 31571 DEFSYM (Qnow, "now");
31230 DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list"); 31572 DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list");
31231 DEFSYM (Qx_auto_preserve_selections, "x-auto-preserve-selections"); 31573 DEFSYM (Qx_auto_preserve_selections, "x-auto-preserve-selections");
31574 DEFSYM (Qexpose, "expose");
31575 DEFSYM (Qdont_save, "dont-save");
31232 31576
31233#ifdef USE_GTK 31577#ifdef USE_GTK
31234 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); 31578 xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
@@ -31398,7 +31742,6 @@ always uses gtk_window_move and ignores the value of this variable. */);
31398This option is only effective when Emacs is built with XInput 2 31742This option is only effective when Emacs is built with XInput 2
31399support. */); 31743support. */);
31400 Vx_scroll_event_delta_factor = make_float (1.0); 31744 Vx_scroll_event_delta_factor = make_float (1.0);
31401 DEFSYM (Qexpose, "expose");
31402 31745
31403 DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input, 31746 DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input,
31404 doc: /* Non-nil means to use GTK for input method support. 31747 doc: /* Non-nil means to use GTK for input method support.
@@ -31612,4 +31955,25 @@ select text over slow X connections.
31612If that is still too slow, setting this variable to the symbol 31955If that is still too slow, setting this variable to the symbol
31613`really-fast' will make Emacs return only cached values. */); 31956`really-fast' will make Emacs return only cached values. */);
31614 Vx_use_fast_mouse_position = Qnil; 31957 Vx_use_fast_mouse_position = Qnil;
31958
31959 DEFVAR_LISP ("x-detect-server-trust", Vx_detect_server_trust,
31960 doc: /* If non-nil, Emacs should detect whether or not it is trusted by X.
31961
31962If non-nil, Emacs will make an X request at connection startup that is
31963prohibited to untrusted clients under the X Security Extension and
31964check whether or not a resulting Access error is generated by the X
31965server. If the X server reports the error, Emacs will disable certain
31966features that do not work for untrusted clients. */);
31967 Vx_detect_server_trust = Qnil;
31968
31969 DEFVAR_LISP ("x-lax-frame-positioning", Vx_lax_frame_positioning,
31970 doc: /* If non-nil, Emacs won't compensate for WM geometry behavior.
31971
31972Setting this to non-nil is useful when the compensation proves to be
31973too slow, which is usually true when the X server is located over a
31974network connection with high latency. Doing so will make frame
31975creation and placement faster at the cost of reducing the accuracy of
31976frame placement via frame parameters, `set-frame-position', and
31977`set-frame-size'. */);
31978 Vx_lax_frame_positioning = Qnil;
31615} 31979}
diff --git a/src/xterm.h b/src/xterm.h
index c36920081d3..832ffc172b9 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -21,6 +21,22 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21#define XTERM_H 21#define XTERM_H
22 22
23#include <X11/Xlib.h> 23#include <X11/Xlib.h>
24
25#ifdef HAVE_XFIXES
26#include <X11/extensions/Xfixes.h>
27
28#if defined HAVE_XINPUT2 && XFIXES_MAJOR < 5
29/* XI2 headers need PointerBarrier, which is not defined in old
30 versions of the fixes library. Define that type here. */
31typedef XID PointerBarrier;
32#endif
33#if defined HAVE_XCOMPOSITE && XFIXES_MAJOR < 2
34/* Recent Composite headers need XserverRegion, which is not defined
35 in old versions of the fixes library. Define that type here. */
36typedef XID XserverRegion;
37#endif
38#endif
39
24#include <X11/cursorfont.h> 40#include <X11/cursorfont.h>
25 41
26/* Include Xutil.h after keysym.h to work around a bug that prevents 42/* Include Xutil.h after keysym.h to work around a bug that prevents
@@ -318,6 +334,9 @@ struct x_failable_request
318 /* If this is zero, then the request has not yet been made. 334 /* If this is zero, then the request has not yet been made.
319 Otherwise, this is the request that ends this sequence. */ 335 Otherwise, this is the request that ends this sequence. */
320 unsigned long end; 336 unsigned long end;
337
338 /* Any selection event serial associated with this error trap. */
339 unsigned int selection_serial;
321}; 340};
322 341
323#ifdef HAVE_XFIXES 342#ifdef HAVE_XFIXES
@@ -360,6 +379,10 @@ struct x_display_info
360 /* Number of frames that are on this display. */ 379 /* Number of frames that are on this display. */
361 int reference_count; 380 int reference_count;
362 381
382 /* True if this display connection cannot communicate with the
383 window manager because it is not trusted by the X server. */
384 bool untrusted;
385
363 /* The Screen this connection is connected to. */ 386 /* The Screen this connection is connected to. */
364 Screen *screen; 387 Screen *screen;
365 388
@@ -406,7 +429,7 @@ struct x_display_info
406 Unused if this display supports Xfixes extension. */ 429 Unused if this display supports Xfixes extension. */
407 Cursor invisible_cursor; 430 Cursor invisible_cursor;
408 431
409#ifdef HAVE_XFIXES 432#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
410 /* Whether or not to use Xfixes for pointer blanking. */ 433 /* Whether or not to use Xfixes for pointer blanking. */
411 bool fixes_pointer_blanking; 434 bool fixes_pointer_blanking;
412#endif 435#endif
@@ -537,6 +560,12 @@ struct x_display_info
537 KDE" protocol in x-dnd.el). */ 560 KDE" protocol in x-dnd.el). */
538 Atom Xatom_DndProtocol, Xatom_DND_PROTOCOL; 561 Atom Xatom_DndProtocol, Xatom_DND_PROTOCOL;
539 562
563 /* Atoms to make x_intern_cached_atom fast. */
564 Atom Xatom_text_plain_charset_utf_8, Xatom_LENGTH, Xatom_FILE_NAME,
565 Xatom_CHARACTER_POSITION, Xatom_LINE_NUMBER, Xatom_COLUMN_NUMBER,
566 Xatom_OWNER_OS, Xatom_HOST_NAME, Xatom_USER, Xatom_CLASS,
567 Xatom_NAME, Xatom_SAVE_TARGETS;
568
540 /* The frame (if any) which has the X window that has keyboard focus. 569 /* The frame (if any) which has the X window that has keyboard focus.
541 Zero if none. This is examined by Ffocus_frame in xfns.c. Note 570 Zero if none. This is examined by Ffocus_frame in xfns.c. Note
542 that a mere EnterNotify event can set this; if you need to know the 571 that a mere EnterNotify event can set this; if you need to know the
@@ -1179,6 +1208,10 @@ struct x_output
1179 frame. */ 1208 frame. */
1180 bool_bf waiting_for_frame_p : 1; 1209 bool_bf waiting_for_frame_p : 1;
1181 1210
1211 /* Whether or not Emacs just skipped waiting for a frame due to a
1212 timeout. */
1213 bool_bf draw_just_hung_p : 1;
1214
1182#if !defined USE_GTK && defined HAVE_CLOCK_GETTIME 1215#if !defined USE_GTK && defined HAVE_CLOCK_GETTIME
1183 /* Whether or not Emacs should wait for the compositing manager to 1216 /* Whether or not Emacs should wait for the compositing manager to
1184 draw frames before starting a new frame. */ 1217 draw frames before starting a new frame. */
@@ -1392,6 +1425,8 @@ extern void x_mark_frame_dirty (struct frame *f);
1392 FRAME_X_OUTPUT (f)->extended_frame_counter 1425 FRAME_X_OUTPUT (f)->extended_frame_counter
1393#define FRAME_X_WAITING_FOR_DRAW(f) \ 1426#define FRAME_X_WAITING_FOR_DRAW(f) \
1394 FRAME_X_OUTPUT (f)->waiting_for_frame_p 1427 FRAME_X_OUTPUT (f)->waiting_for_frame_p
1428#define FRAME_X_DRAW_JUST_HUNG(f) \
1429 FRAME_X_OUTPUT (f)->draw_just_hung_p
1395#define FRAME_X_COUNTER_VALUE(f) \ 1430#define FRAME_X_COUNTER_VALUE(f) \
1396 FRAME_X_OUTPUT (f)->current_extended_counter_value 1431 FRAME_X_OUTPUT (f)->current_extended_counter_value
1397#endif 1432#endif
@@ -1638,7 +1673,8 @@ extern bool x_had_errors_p (Display *);
1638extern void x_unwind_errors_to (int); 1673extern void x_unwind_errors_to (int);
1639extern void x_uncatch_errors (void); 1674extern void x_uncatch_errors (void);
1640extern void x_uncatch_errors_after_check (void); 1675extern void x_uncatch_errors_after_check (void);
1641extern void x_ignore_errors_for_next_request (struct x_display_info *); 1676extern void x_ignore_errors_for_next_request (struct x_display_info *,
1677 unsigned int);
1642extern void x_stop_ignoring_errors (struct x_display_info *); 1678extern void x_stop_ignoring_errors (struct x_display_info *);
1643extern void x_clear_errors (Display *); 1679extern void x_clear_errors (Display *);
1644extern void x_set_window_size (struct frame *, bool, int, int); 1680extern void x_set_window_size (struct frame *, bool, int, int);
@@ -1711,6 +1747,11 @@ extern Lisp_Object x_handle_translate_coordinates (struct frame *, Lisp_Object,
1711 1747
1712extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *, 1748extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *,
1713 int *, int *, int *, unsigned int *); 1749 int *, int *, int *, unsigned int *);
1750extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
1751 bool);
1752extern void x_intern_atoms (struct x_display_info *, char **, int, Atom *);
1753extern char *x_get_atom_name (struct x_display_info *, Atom, bool *)
1754 ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE;
1714 1755
1715#ifdef HAVE_GTK3 1756#ifdef HAVE_GTK3
1716extern void x_scroll_bar_configure (GdkEvent *); 1757extern void x_scroll_bar_configure (GdkEvent *);
@@ -1792,6 +1833,9 @@ extern void x_handle_property_notify (const XPropertyEvent *);
1792extern void x_handle_selection_notify (const XSelectionEvent *); 1833extern void x_handle_selection_notify (const XSelectionEvent *);
1793extern void x_handle_selection_event (struct selection_input_event *); 1834extern void x_handle_selection_event (struct selection_input_event *);
1794extern void x_clear_frame_selections (struct frame *); 1835extern void x_clear_frame_selections (struct frame *);
1836extern void x_remove_selection_transfers (struct x_display_info *);
1837extern void x_handle_selection_error (unsigned int, XErrorEvent *);
1838
1795extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom); 1839extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom);
1796extern Atom symbol_to_x_atom (struct x_display_info *, Lisp_Object); 1840extern Atom symbol_to_x_atom (struct x_display_info *, Lisp_Object);
1797 1841
@@ -1801,11 +1845,8 @@ extern bool x_handle_dnd_message (struct frame *,
1801 struct input_event *, 1845 struct input_event *,
1802 bool, int, int); 1846 bool, int, int);
1803extern int x_check_property_data (Lisp_Object); 1847extern int x_check_property_data (Lisp_Object);
1804extern void x_fill_property_data (Display *, 1848extern void x_fill_property_data (struct x_display_info *, Lisp_Object,
1805 Lisp_Object, 1849 void *, int, int);
1806 void *,
1807 int,
1808 int);
1809extern Lisp_Object x_property_data_to_lisp (struct frame *, 1850extern Lisp_Object x_property_data_to_lisp (struct frame *,
1810 const unsigned char *, 1851 const unsigned char *,
1811 Atom, 1852 Atom,
@@ -1818,10 +1859,10 @@ extern Lisp_Object x_timestamp_for_selection (struct x_display_info *,
1818 Lisp_Object); 1859 Lisp_Object);
1819extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object, 1860extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object,
1820 Lisp_Object, Time); 1861 Lisp_Object, Time);
1821extern Atom x_intern_cached_atom (struct x_display_info *, const char *, 1862
1822 bool); 1863extern void mark_xselect (void);
1823extern char *x_get_atom_name (struct x_display_info *, Atom, bool *) 1864
1824 ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE; 1865/* Misc definitions. */
1825 1866
1826#ifdef USE_GTK 1867#ifdef USE_GTK
1827extern bool xg_set_icon (struct frame *, Lisp_Object); 1868extern bool xg_set_icon (struct frame *, Lisp_Object);