aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-12-31 18:05:12 +0800
committerPo Lu2022-12-31 18:05:12 +0800
commitfd074f3133a348dd1d3b7ee569f0fc046223efb9 (patch)
treeac82e56578f398be747175f0f42ca2b3cb0ca0b8 /src
parentcfbc8a5dbcd362b69b37b4e6832ae4a31834364c (diff)
parentf59d012af7e607448fdb435fcb4becb6a6ebe665 (diff)
downloademacs-fd074f3133a348dd1d3b7ee569f0fc046223efb9.tar.gz
emacs-fd074f3133a348dd1d3b7ee569f0fc046223efb9.zip
Merge remote-tracking branch 'origin/master' into feature/android
Diffstat (limited to 'src')
-rw-r--r--src/dispnew.c2
-rw-r--r--src/emacs.c1
-rw-r--r--src/eval.c6
-rw-r--r--src/frame.h14
-rw-r--r--src/gnutls.c142
-rw-r--r--src/indent.c2
-rw-r--r--src/json.c79
-rw-r--r--src/keyboard.c5
-rw-r--r--src/lisp.h1
-rw-r--r--src/process.c11
-rw-r--r--src/treesit.c289
-rw-r--r--src/w32menu.c13
-rw-r--r--src/w32term.c11
-rw-r--r--src/xdisp.c40
-rw-r--r--src/xfns.c1
-rw-r--r--src/xterm.c6
-rw-r--r--src/xterm.h10
17 files changed, 467 insertions, 166 deletions
diff --git a/src/dispnew.c b/src/dispnew.c
index ed10accac7b..6fc91e60eb5 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3194,7 +3194,7 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
3194 Lisp_Object tail, frame; 3194 Lisp_Object tail, frame;
3195 3195
3196 FOR_EACH_FRAME (tail, frame) 3196 FOR_EACH_FRAME (tail, frame)
3197 if (FRAME_VISIBLE_P (XFRAME (frame))) 3197 if (FRAME_REDISPLAY_P (XFRAME (frame)))
3198 redraw_frame (XFRAME (frame)); 3198 redraw_frame (XFRAME (frame));
3199 3199
3200 return Qnil; 3200 return Qnil;
diff --git a/src/emacs.c b/src/emacs.c
index b6686f88096..9ef58ca412e 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2938,6 +2938,7 @@ killed. */
2938 2938
2939 if (!NILP (restart)) 2939 if (!NILP (restart))
2940 { 2940 {
2941 turn_on_atimers (false);
2941#ifdef WINDOWSNT 2942#ifdef WINDOWSNT
2942 if (w32_reexec_emacs (initial_cmdline, initial_wd) < 0) 2943 if (w32_reexec_emacs (initial_cmdline, initial_wd) < 0)
2943#else 2944#else
diff --git a/src/eval.c b/src/eval.c
index 99f3650fc9b..cff4b924778 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1367,7 +1367,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1367 error ("Invalid condition handler: %s", 1367 error ("Invalid condition handler: %s",
1368 SDATA (Fprin1_to_string (tem, Qt, Qnil))); 1368 SDATA (Fprin1_to_string (tem, Qt, Qnil)));
1369 if (CONSP (tem) && EQ (XCAR (tem), QCsuccess)) 1369 if (CONSP (tem) && EQ (XCAR (tem), QCsuccess))
1370 success_handler = XCDR (tem); 1370 success_handler = tem;
1371 else 1371 else
1372 clausenb++; 1372 clausenb++;
1373 } 1373 }
@@ -1430,7 +1430,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1430 if (!NILP (success_handler)) 1430 if (!NILP (success_handler))
1431 { 1431 {
1432 if (NILP (var)) 1432 if (NILP (var))
1433 return Fprogn (success_handler); 1433 return Fprogn (XCDR (success_handler));
1434 1434
1435 Lisp_Object handler_var = var; 1435 Lisp_Object handler_var = var;
1436 if (!NILP (Vinternal_interpreter_environment)) 1436 if (!NILP (Vinternal_interpreter_environment))
@@ -1442,7 +1442,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1442 1442
1443 specpdl_ref count = SPECPDL_INDEX (); 1443 specpdl_ref count = SPECPDL_INDEX ();
1444 specbind (handler_var, result); 1444 specbind (handler_var, result);
1445 return unbind_to (count, Fprogn (success_handler)); 1445 return unbind_to (count, Fprogn (XCDR (success_handler)));
1446 } 1446 }
1447 return result; 1447 return result;
1448} 1448}
diff --git a/src/frame.h b/src/frame.h
index e0b47d26d69..e5693e0877d 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1025,6 +1025,20 @@ default_pixels_per_inch_y (void)
1025/* True if frame F is currently visible. */ 1025/* True if frame F is currently visible. */
1026#define FRAME_VISIBLE_P(f) (f)->visible 1026#define FRAME_VISIBLE_P(f) (f)->visible
1027 1027
1028/* True if frame F should be redisplayed. This is normally the same
1029 as FRAME_VISIBLE_P (f). Under X, frames can continue to be
1030 displayed to the user by the compositing manager even if they are
1031 invisible, so this also checks whether or not the frame is reported
1032 visible by the X server. */
1033
1034#ifndef HAVE_X_WINDOWS
1035#define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f))
1036#else
1037#define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f) \
1038 || (FRAME_X_P (f) \
1039 && FRAME_X_VISIBLE (f)))
1040#endif
1041
1028/* True if frame F is currently visible but hidden. */ 1042/* True if frame F is currently visible but hidden. */
1029#define FRAME_OBSCURED_P(f) ((f)->visible > 1) 1043#define FRAME_OBSCURED_P(f) ((f)->visible > 1)
1030 1044
diff --git a/src/gnutls.c b/src/gnutls.c
index 4093865cae5..e58322934de 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -34,6 +34,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
34# endif 34# endif
35 35
36# if GNUTLS_VERSION_NUMBER >= 0x030200 36# if GNUTLS_VERSION_NUMBER >= 0x030200
37# define HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
37# define HAVE_GNUTLS_CIPHER_GET_IV_SIZE 38# define HAVE_GNUTLS_CIPHER_GET_IV_SIZE
38# endif 39# endif
39 40
@@ -121,6 +122,11 @@ DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
121DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file, 122DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
122 (gnutls_certificate_credentials_t, const char *, const char *, 123 (gnutls_certificate_credentials_t, const char *, const char *,
123 gnutls_x509_crt_fmt_t)); 124 gnutls_x509_crt_fmt_t));
125# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
126DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file2,
127 (gnutls_certificate_credentials_t, const char *, const char *,
128 gnutls_x509_crt_fmt_t, const char *, unsigned int));
129# endif
124# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST 130# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
125DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust, 131DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
126 (gnutls_certificate_credentials_t)); 132 (gnutls_certificate_credentials_t));
@@ -314,6 +320,9 @@ init_gnutls_functions (void)
314 LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags); 320 LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
315 LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file); 321 LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
316 LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file); 322 LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
323# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
324 LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file2);
325# endif
317# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST 326# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
318 LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust); 327 LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
319# endif 328# endif
@@ -455,6 +464,9 @@ init_gnutls_functions (void)
455# define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags 464# define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
456# define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file 465# define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
457# define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file 466# define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
467# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
468# define gnutls_certificate_set_x509_key_file2 fn_gnutls_certificate_set_x509_key_file2
469# endif
458# define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust 470# define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
459# define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file 471# define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
460# define gnutls_certificate_type_get fn_gnutls_certificate_type_get 472# define gnutls_certificate_type_get fn_gnutls_certificate_type_get
@@ -1774,6 +1786,72 @@ gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
1774 return gnutls_make_error (ret); 1786 return gnutls_make_error (ret);
1775} 1787}
1776 1788
1789#ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
1790
1791/* Helper function for gnutls-boot.
1792
1793 The key :flags receives a list of symbols, each of which
1794 corresponds to a GnuTLS C flag, the ORed result is to be passed to
1795 the function `gnutls_certificate_set_x509_key_file2' as its last
1796 argument. */
1797static unsigned int
1798key_file2_aux (Lisp_Object flags)
1799{
1800 unsigned int rv = 0;
1801 Lisp_Object tail = flags;
1802 FOR_EACH_TAIL_SAFE (tail)
1803 {
1804 Lisp_Object flag = XCAR (tail);
1805 if (EQ (flag, Qgnutls_pkcs_plain))
1806 rv |= GNUTLS_PKCS_PLAIN;
1807 else if (EQ (flag, Qgnutls_pkcs_pkcs12_3des))
1808 rv |= GNUTLS_PKCS_PKCS12_3DES;
1809 else if (EQ (flag, Qgnutls_pkcs_pkcs12_arcfour))
1810 rv |= GNUTLS_PKCS_PKCS12_ARCFOUR;
1811 else if (EQ (flag, Qgnutls_pkcs_pkcs12_rc2_40))
1812 rv |= GNUTLS_PKCS_PKCS12_RC2_40;
1813 else if (EQ (flag, Qgnutls_pkcs_pbes2_3des))
1814 rv |= GNUTLS_PKCS_PBES2_3DES;
1815 else if (EQ (flag, Qgnutls_pkcs_pbes2_aes_128))
1816 rv |= GNUTLS_PKCS_PBES2_AES_128;
1817 else if (EQ (flag, Qgnutls_pkcs_pbes2_aes_192))
1818 rv |= GNUTLS_PKCS_PBES2_AES_192;
1819 else if (EQ (flag, Qgnutls_pkcs_pbes2_aes_256))
1820 rv |= GNUTLS_PKCS_PBES2_AES_256;
1821 else if (EQ (flag, Qgnutls_pkcs_null_password))
1822 rv |= GNUTLS_PKCS_NULL_PASSWORD;
1823 else if (EQ (flag, Qgnutls_pkcs_pbes2_des))
1824 rv |= GNUTLS_PKCS_PBES2_DES;
1825#ifdef GNUTLS_PKCS_PBES1_DES_MD5
1826 else if (EQ (flag, Qgnutls_pkcs_pbes1_des_md5))
1827 rv |= GNUTLS_PKCS_PBES1_DES_MD5;
1828#endif
1829#ifdef GNUTLS_PKCS_PBES2_GOST_TC26Z
1830 else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_tc26z))
1831 rv |= GNUTLS_PKCS_PBES2_GOST_TC26Z;
1832#endif
1833#ifdef GNUTLS_PKCS_PBES2_GOST_CPA
1834 else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpa))
1835 rv |= GNUTLS_PKCS_PBES2_GOST_CPA;
1836#endif
1837#ifdef GNUTLS_PKCS_PBES2_GOST_CPB
1838 else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpb))
1839 rv |= GNUTLS_PKCS_PBES2_GOST_CPB;
1840#endif
1841#ifdef GNUTLS_PKCS_PBES2_GOST_CPC
1842 else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpc))
1843 rv |= GNUTLS_PKCS_PBES2_GOST_CPC;
1844#endif
1845#ifdef GNUTLS_PKCS_PBES2_GOST_CPD
1846 else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpd))
1847 rv |= GNUTLS_PKCS_PBES2_GOST_CPD;
1848#endif
1849 }
1850 return rv;
1851}
1852
1853#endif /* HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 */
1854
1777DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0, 1855DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
1778 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST. 1856 doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
1779Currently only client mode is supported. Return a success/failure 1857Currently only client mode is supported. Return a success/failure
@@ -1813,6 +1891,22 @@ accept in Diffie-Hellman key exchange.
1813:complete-negotiation, if non-nil, will make negotiation complete 1891:complete-negotiation, if non-nil, will make negotiation complete
1814before returning even on non-blocking sockets. 1892before returning even on non-blocking sockets.
1815 1893
1894:pass, the password of the private key as per GnuTLS'
1895gnutls_certificate_set_x509_key_file2. Specify as nil to have a NULL
1896password.
1897
1898:flags, a list of symbols relating to :pass, each specifying a flag:
1899GNUTLS_PKCS_PLAIN, GNUTLS_PKCS_PKCS12_3DES,
1900GNUTLS_PKCS_PKCS12_ARCFOUR, GNUTLS_PKCS_PKCS12_RC2_40,
1901GNUTLS_PKCS_PBES2_3DES, GNUTLS_PKCS_PBES2_AES_128,
1902GNUTLS_PKCS_PBES2_AES_192, GNUTLS_PKCS_PBES2_AES_256,
1903GNUTLS_PKCS_NULL_PASSWORD, GNUTLS_PKCS_PBES2_DES,
1904GNUTLS_PKCS_PBES2_DES_MD5, GNUTLS_PKCS_PBES2_GOST_TC26Z,
1905GNUTLS_PKCS_PBES2_GOST_CPA, GNUTLS_PKCS_PBES2_GOST_CPB,
1906GNUTLS_PKCS_PBES2_GOST_CPC, GNUTLS_PKCS_PBES2_GOST_CPD. If not
1907specified, or if nil, the bitflag with value 0 is used.
1908Note that some of these are only supported since GnuTLS 3.6.3.
1909
1816The debug level will be set for this process AND globally for GnuTLS. 1910The debug level will be set for this process AND globally for GnuTLS.
1817So if you set it higher or lower at any point, it affects global 1911So if you set it higher or lower at any point, it affects global
1818debugging. 1912debugging.
@@ -1825,6 +1919,9 @@ Processes must be initialized with this function before other GnuTLS
1825functions are used. This function allocates resources which can only 1919functions are used. This function allocates resources which can only
1826be deallocated by calling `gnutls-deinit' or by calling it again. 1920be deallocated by calling `gnutls-deinit' or by calling it again.
1827 1921
1922The :pass and :flags keys are ignored with old versions of GnuTLS, and
1923:flags is ignored if :pass is not specified.
1924
1828The callbacks alist can have a `verify' key, associated with a 1925The callbacks alist can have a `verify' key, associated with a
1829verification function (UNUSED). 1926verification function (UNUSED).
1830 1927
@@ -1842,16 +1939,22 @@ one trustfile (usually a CA bundle). */)
1842 Lisp_Object global_init; 1939 Lisp_Object global_init;
1843 char const *priority_string_ptr = "NORMAL"; /* default priority string. */ 1940 char const *priority_string_ptr = "NORMAL"; /* default priority string. */
1844 char *c_hostname; 1941 char *c_hostname;
1942 const char *c_pass;
1845 1943
1846 /* Placeholders for the property list elements. */ 1944 /* Placeholders for the property list elements. */
1847 Lisp_Object priority_string; 1945 Lisp_Object priority_string;
1848 Lisp_Object trustfiles; 1946 Lisp_Object trustfiles;
1849 Lisp_Object crlfiles; 1947 Lisp_Object crlfiles;
1850 Lisp_Object keylist; 1948 Lisp_Object keylist;
1949 Lisp_Object pass;
1950 Lisp_Object flags;
1851 /* Lisp_Object callbacks; */ 1951 /* Lisp_Object callbacks; */
1852 Lisp_Object loglevel; 1952 Lisp_Object loglevel;
1853 Lisp_Object hostname; 1953 Lisp_Object hostname;
1854 Lisp_Object prime_bits; 1954 Lisp_Object prime_bits;
1955#ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
1956 unsigned int aux_key_file;
1957#endif
1855 struct Lisp_Process *p = XPROCESS (proc); 1958 struct Lisp_Process *p = XPROCESS (proc);
1856 1959
1857 CHECK_PROCESS (proc); 1960 CHECK_PROCESS (proc);
@@ -1877,6 +1980,13 @@ one trustfile (usually a CA bundle). */)
1877 crlfiles = plist_get (proplist, QCcrlfiles); 1980 crlfiles = plist_get (proplist, QCcrlfiles);
1878 loglevel = plist_get (proplist, QCloglevel); 1981 loglevel = plist_get (proplist, QCloglevel);
1879 prime_bits = plist_get (proplist, QCmin_prime_bits); 1982 prime_bits = plist_get (proplist, QCmin_prime_bits);
1983 pass = plist_get (proplist, QCpass);
1984 flags = plist_get (proplist, QCflags);
1985
1986 if (STRINGP (pass))
1987 c_pass = SSDATA (pass);
1988 else
1989 c_pass = NULL;
1880 1990
1881 if (!STRINGP (hostname)) 1991 if (!STRINGP (hostname))
1882 { 1992 {
@@ -2038,6 +2148,20 @@ one trustfile (usually a CA bundle). */)
2038 keyfile = ansi_encode_filename (keyfile); 2148 keyfile = ansi_encode_filename (keyfile);
2039 certfile = ansi_encode_filename (certfile); 2149 certfile = ansi_encode_filename (certfile);
2040# endif 2150# endif
2151# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
2152 if (!NILP (plist_member (proplist, QCpass)))
2153 {
2154 aux_key_file = key_file2_aux (flags);
2155 ret
2156 = gnutls_certificate_set_x509_key_file2 (x509_cred,
2157 SSDATA (certfile),
2158 SSDATA (keyfile),
2159 file_format,
2160 c_pass,
2161 aux_key_file);
2162 }
2163 else
2164# endif
2041 ret = gnutls_certificate_set_x509_key_file 2165 ret = gnutls_certificate_set_x509_key_file
2042 (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format); 2166 (x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
2043 2167
@@ -2862,8 +2986,26 @@ level in the ones. For builds without libgnutls, the value is -1. */);
2862 DEFSYM (QCmin_prime_bits, ":min-prime-bits"); 2986 DEFSYM (QCmin_prime_bits, ":min-prime-bits");
2863 DEFSYM (QCloglevel, ":loglevel"); 2987 DEFSYM (QCloglevel, ":loglevel");
2864 DEFSYM (QCcomplete_negotiation, ":complete-negotiation"); 2988 DEFSYM (QCcomplete_negotiation, ":complete-negotiation");
2989 DEFSYM (QCpass, ":pass");
2990 DEFSYM (QCflags, ":flags");
2865 DEFSYM (QCverify_flags, ":verify-flags"); 2991 DEFSYM (QCverify_flags, ":verify-flags");
2866 DEFSYM (QCverify_error, ":verify-error"); 2992 DEFSYM (QCverify_error, ":verify-error");
2993 DEFSYM (Qgnutls_pkcs_plain, "GNUTLS_PKCS_PLAIN");
2994 DEFSYM (Qgnutls_pkcs_pkcs12_3des, "GNUTLS_PKCS_PKCS12_3DES");
2995 DEFSYM (Qgnutls_pkcs_pkcs12_arcfour, "GNUTLS_PKCS_PKCS12_ARCFOUR");
2996 DEFSYM (Qgnutls_pkcs_pkcs12_rc2_40, "GNUTLS_PKCS_PKCS12_RC2_40");
2997 DEFSYM (Qgnutls_pkcs_pbes2_3des, "GNUTLS_PKCS_PBES2_3DES");
2998 DEFSYM (Qgnutls_pkcs_pbes2_aes_128, "GNUTLS_PKCS_PBES2_AES_128");
2999 DEFSYM (Qgnutls_pkcs_pbes2_aes_192, "GNUTLS_PKCS_PBES2_AES_192");
3000 DEFSYM (Qgnutls_pkcs_pbes2_aes_256, "GNUTLS_PKCS_PBES2_AES_256");
3001 DEFSYM (Qgnutls_pkcs_null_password, "GNUTLS_PKCS_NULL_PASSWORD");
3002 DEFSYM (Qgnutls_pkcs_pbes2_des, "GNUTLS_PKCS_PBES2_DES");
3003 DEFSYM (Qgnutls_pkcs_pbes1_des_md5, "GNUTLS_PKCS_PBES1_DES_MD5");
3004 DEFSYM (Qgnutls_pkcs_pbes2_gost_tc26z, "GNUTLS_PKCS_PBES2_GOST_TC26Z");
3005 DEFSYM (Qgnutls_pkcs_pbes2_gost_cpa, "GNUTLS_PKCS_PBES2_GOST_CPA");
3006 DEFSYM (Qgnutls_pkcs_pbes2_gost_cpb, "GNUTLS_PKCS_PBES2_GOST_CPB");
3007 DEFSYM (Qgnutls_pkcs_pbes2_gost_cpc, "GNUTLS_PKCS_PBES2_GOST_CPC");
3008 DEFSYM (Qgnutls_pkcs_pbes2_gost_cpd, "GNUTLS_PKCS_PBES2_GOST_CPD");
2867 3009
2868 DEFSYM (QCcipher_id, ":cipher-id"); 3010 DEFSYM (QCcipher_id, ":cipher-id");
2869 DEFSYM (QCcipher_aead_capable, ":cipher-aead-capable"); 3011 DEFSYM (QCcipher_aead_capable, ":cipher-aead-capable");
diff --git a/src/indent.c b/src/indent.c
index 4671ccccf90..66edaff67de 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -887,6 +887,8 @@ DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
887Optional second argument MINIMUM says always do at least MINIMUM spaces 887Optional second argument MINIMUM says always do at least MINIMUM spaces
888even if that goes past COLUMN; by default, MINIMUM is zero. 888even if that goes past COLUMN; by default, MINIMUM is zero.
889 889
890Whether this uses tabs or spaces depends on `indent-tabs-mode'.
891
890The return value is the column where the insertion ends. */) 892The return value is the column where the insertion ends. */)
891 (Lisp_Object column, Lisp_Object minimum) 893 (Lisp_Object column, Lisp_Object minimum)
892{ 894{
diff --git a/src/json.c b/src/json.c
index cdcc11358e6..621c7d7c15f 100644
--- a/src/json.c
+++ b/src/json.c
@@ -555,6 +555,40 @@ json_parse_args (ptrdiff_t nargs,
555 } 555 }
556} 556}
557 557
558static bool
559json_available_p (void)
560{
561#ifdef WINDOWSNT
562 if (!json_initialized)
563 {
564 Lisp_Object status;
565 json_initialized = init_json_functions ();
566 status = json_initialized ? Qt : Qnil;
567 Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
568 }
569 return json_initialized;
570#else /* !WINDOWSNT */
571 return true;
572#endif
573}
574
575#ifdef WINDOWSNT
576static void
577ensure_json_available (void)
578{
579 if (!json_available_p ())
580 Fsignal (Qjson_unavailable,
581 list1 (build_unibyte_string ("jansson library not found")));
582}
583#endif
584
585DEFUN ("json--available-p", Fjson__available_p, Sjson__available_p, 0, 0, NULL,
586 doc: /* Return non-nil if libjansson is available (internal use only). */)
587 (void)
588{
589 return json_available_p () ? Qt : Qnil;
590}
591
558DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, MANY, 592DEFUN ("json-serialize", Fjson_serialize, Sjson_serialize, 1, MANY,
559 NULL, 593 NULL,
560 doc: /* Return the JSON representation of OBJECT as a string. 594 doc: /* Return the JSON representation of OBJECT as a string.
@@ -587,16 +621,7 @@ usage: (json-serialize OBJECT &rest ARGS) */)
587 specpdl_ref count = SPECPDL_INDEX (); 621 specpdl_ref count = SPECPDL_INDEX ();
588 622
589#ifdef WINDOWSNT 623#ifdef WINDOWSNT
590 if (!json_initialized) 624 ensure_json_available ();
591 {
592 Lisp_Object status;
593 json_initialized = init_json_functions ();
594 status = json_initialized ? Qt : Qnil;
595 Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
596 }
597 if (!json_initialized)
598 Fsignal (Qjson_unavailable,
599 list1 (build_unibyte_string ("jansson library not found")));
600#endif 625#endif
601 626
602 struct json_configuration conf = 627 struct json_configuration conf =
@@ -696,16 +721,7 @@ usage: (json-insert OBJECT &rest ARGS) */)
696 specpdl_ref count = SPECPDL_INDEX (); 721 specpdl_ref count = SPECPDL_INDEX ();
697 722
698#ifdef WINDOWSNT 723#ifdef WINDOWSNT
699 if (!json_initialized) 724 ensure_json_available ();
700 {
701 Lisp_Object status;
702 json_initialized = init_json_functions ();
703 status = json_initialized ? Qt : Qnil;
704 Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
705 }
706 if (!json_initialized)
707 Fsignal (Qjson_unavailable,
708 list1 (build_unibyte_string ("jansson library not found")));
709#endif 725#endif
710 726
711 struct json_configuration conf = 727 struct json_configuration conf =
@@ -953,16 +969,7 @@ usage: (json-parse-string STRING &rest ARGS) */)
953 specpdl_ref count = SPECPDL_INDEX (); 969 specpdl_ref count = SPECPDL_INDEX ();
954 970
955#ifdef WINDOWSNT 971#ifdef WINDOWSNT
956 if (!json_initialized) 972 ensure_json_available ();
957 {
958 Lisp_Object status;
959 json_initialized = init_json_functions ();
960 status = json_initialized ? Qt : Qnil;
961 Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
962 }
963 if (!json_initialized)
964 Fsignal (Qjson_unavailable,
965 list1 (build_unibyte_string ("jansson library not found")));
966#endif 973#endif
967 974
968 Lisp_Object string = args[0]; 975 Lisp_Object string = args[0];
@@ -1050,16 +1057,7 @@ usage: (json-parse-buffer &rest args) */)
1050 specpdl_ref count = SPECPDL_INDEX (); 1057 specpdl_ref count = SPECPDL_INDEX ();
1051 1058
1052#ifdef WINDOWSNT 1059#ifdef WINDOWSNT
1053 if (!json_initialized) 1060 ensure_json_available ();
1054 {
1055 Lisp_Object status;
1056 json_initialized = init_json_functions ();
1057 status = json_initialized ? Qt : Qnil;
1058 Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
1059 }
1060 if (!json_initialized)
1061 Fsignal (Qjson_unavailable,
1062 list1 (build_unibyte_string ("jansson library not found")));
1063#endif 1061#endif
1064 1062
1065 struct json_configuration conf = 1063 struct json_configuration conf =
@@ -1137,6 +1135,7 @@ syms_of_json (void)
1137 DEFSYM (Qplist, "plist"); 1135 DEFSYM (Qplist, "plist");
1138 DEFSYM (Qarray, "array"); 1136 DEFSYM (Qarray, "array");
1139 1137
1138 defsubr (&Sjson__available_p);
1140 defsubr (&Sjson_serialize); 1139 defsubr (&Sjson_serialize);
1141 defsubr (&Sjson_insert); 1140 defsubr (&Sjson_insert);
1142 defsubr (&Sjson_parse_string); 1141 defsubr (&Sjson_parse_string);
diff --git a/src/keyboard.c b/src/keyboard.c
index d68b50428a9..7bf89ac7d4b 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -503,11 +503,10 @@ echo_add_key (Lisp_Object c)
503 if ((NILP (echo_string) || SCHARS (echo_string) == 0) 503 if ((NILP (echo_string) || SCHARS (echo_string) == 0)
504 && help_char_p (c)) 504 && help_char_p (c))
505 { 505 {
506 AUTO_STRING (str, " (Type ? for further options, q for quick help)"); 506 AUTO_STRING (str, " (Type ? for further options, C-q for quick help)");
507 AUTO_LIST2 (props, Qface, Qhelp_key_binding); 507 AUTO_LIST2 (props, Qface, Qhelp_key_binding);
508 Fadd_text_properties (make_fixnum (7), make_fixnum (8), props, str); 508 Fadd_text_properties (make_fixnum (7), make_fixnum (8), props, str);
509 Fadd_text_properties (make_fixnum (30), make_fixnum (31), props, 509 Fadd_text_properties (make_fixnum (30), make_fixnum (33), props, str);
510str);
511 new_string = concat2 (new_string, str); 510 new_string = concat2 (new_string, str);
512 } 511 }
513 512
diff --git a/src/lisp.h b/src/lisp.h
index 1f1d47f2a95..d6525ebdc52 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
22 22
23#include <alloca.h> 23#include <alloca.h>
24#include <setjmp.h> 24#include <setjmp.h>
25#include <stdalign.h>
26#include <stdarg.h> 25#include <stdarg.h>
27#include <stddef.h> 26#include <stddef.h>
28#include <string.h> 27#include <string.h>
diff --git a/src/process.c b/src/process.c
index de1b07a81cc..a4be68f7418 100644
--- a/src/process.c
+++ b/src/process.c
@@ -6810,10 +6810,13 @@ emacs_get_tty_pgrp (struct Lisp_Process *p)
6810 6810
6811DEFUN ("process-running-child-p", Fprocess_running_child_p, 6811DEFUN ("process-running-child-p", Fprocess_running_child_p,
6812 Sprocess_running_child_p, 0, 1, 0, 6812 Sprocess_running_child_p, 0, 1, 0,
6813 doc: /* Return non-nil if PROCESS has given the terminal to a 6813 doc: /* Return non-nil if PROCESS has given control of its terminal to a child.
6814child. If the operating system does not make it possible to find out, 6814If the operating system does not make it possible to find out, return t.
6815return t. If we can find out, return the numeric ID of the foreground 6815If it's possible to find out, return the numeric ID of the foreground
6816process group. */) 6816process group if PROCESS did give control of its terminal to a
6817child process, and return nil if it didn't.
6818
6819PROCESS must be a real subprocess, not a connection. */)
6817 (Lisp_Object process) 6820 (Lisp_Object process)
6818{ 6821{
6819 /* Initialize in case ioctl doesn't exist or gives an error, 6822 /* Initialize in case ioctl doesn't exist or gives an error,
diff --git a/src/treesit.c b/src/treesit.c
index c882d455137..974d2fc4517 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -2,6 +2,8 @@
2 2
3Copyright (C) 2021-2022 Free Software Foundation, Inc. 3Copyright (C) 2021-2022 Free Software Foundation, Inc.
4 4
5Maintainer: Yuan Fu <casouri@gmail.com>
6
5This file is part of GNU Emacs. 7This file is part of GNU Emacs.
6 8
7GNU Emacs is free software: you can redistribute it and/or modify 9GNU Emacs is free software: you can redistribute it and/or modify
@@ -404,6 +406,10 @@ init_treesit_functions (void)
404 406
405/*** Initialization */ 407/*** Initialization */
406 408
409/* This is the limit on recursion levels for some tree-sitter
410 functions. Remember to update docstrings when changing this
411 value. */
412const ptrdiff_t treesit_recursion_limit = 1000;
407bool treesit_initialized = false; 413bool treesit_initialized = false;
408 414
409static bool 415static bool
@@ -656,9 +662,8 @@ If DETAIL is non-nil, return (t . nil) when LANGUAGE is available,
656 } 662 }
657} 663}
658 664
659DEFUN ("treesit-language-version", 665DEFUN ("treesit-library-abi-version", Ftreesit_library_abi_version,
660 Ftreesit_language_version, 666 Streesit_library_abi_version,
661 Streesit_language_version,
662 0, 1, 0, 667 0, 1, 0,
663 doc: /* Return the language ABI version of the tree-sitter library. 668 doc: /* Return the language ABI version of the tree-sitter library.
664 669
@@ -674,6 +679,29 @@ is non-nil, return the oldest compatible ABI version. */)
674 return make_fixnum (TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION); 679 return make_fixnum (TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION);
675} 680}
676 681
682DEFUN ("treesit-language-version", Ftreesit_language_abi_version,
683 Streesit_language_abi_version,
684 0, 1, 0,
685 doc: /* Return the language ABI version of the tree-sitter LANGUAGE.
686Return nil if LANGUAGE is not available. */)
687 (Lisp_Object language)
688{
689 if (NILP (Ftreesit_langauge_available_p (language, Qnil)))
690 return Qnil;
691 else
692 {
693 Lisp_Object signal_symbol = Qnil;
694 Lisp_Object signal_data = Qnil;
695 TSLanguage *ts_language = treesit_load_language (language,
696 &signal_symbol,
697 &signal_data);
698 if (ts_language == NULL)
699 return Qnil;
700 uint32_t version = ts_language_version (ts_language);
701 return make_fixnum((ptrdiff_t) version);
702 }
703}
704
677/*** Parsing functions */ 705/*** Parsing functions */
678 706
679static void 707static void
@@ -927,11 +955,24 @@ static void
927treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree, 955treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree,
928 Lisp_Object parser) 956 Lisp_Object parser)
929{ 957{
930 uint32_t len; 958 /* If the old_tree is NULL, meaning this is the first parse, the
931 TSRange *ranges = ts_tree_get_changed_ranges (old_tree, new_tree, &len); 959 changed range is the whole buffer. */
960 Lisp_Object lisp_ranges;
932 struct buffer *buf = XBUFFER (XTS_PARSER (parser)->buffer); 961 struct buffer *buf = XBUFFER (XTS_PARSER (parser)->buffer);
933 Lisp_Object lisp_ranges = treesit_make_ranges (ranges, len, buf); 962 if (old_tree)
934 xfree (ranges); 963 {
964 uint32_t len;
965 TSRange *ranges = ts_tree_get_changed_ranges (old_tree, new_tree, &len);
966 lisp_ranges = treesit_make_ranges (ranges, len, buf);
967 xfree (ranges);
968 }
969 else
970 {
971 struct buffer *oldbuf = current_buffer;
972 set_buffer_internal (buf);
973 lisp_ranges = Fcons (Fcons (Fpoint_min (), Fpoint_max ()), Qnil);
974 set_buffer_internal (oldbuf);
975 }
935 976
936 specpdl_ref count = SPECPDL_INDEX (); 977 specpdl_ref count = SPECPDL_INDEX ();
937 978
@@ -949,6 +990,11 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree,
949static void 990static void
950treesit_ensure_parsed (Lisp_Object parser) 991treesit_ensure_parsed (Lisp_Object parser)
951{ 992{
993 /* Make sure this comes before everything else, see comment
994 (ref:notifier-inside-ensure-parsed) for more detail. */
995 if (!XTS_PARSER (parser)->need_reparse)
996 return;
997
952 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer); 998 struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
953 999
954 /* Before we parse, catch up with the narrowing situation. */ 1000 /* Before we parse, catch up with the narrowing situation. */
@@ -957,8 +1003,6 @@ treesit_ensure_parsed (Lisp_Object parser)
957 because it might set the flag to true. */ 1003 because it might set the flag to true. */
958 treesit_sync_visible_region (parser); 1004 treesit_sync_visible_region (parser);
959 1005
960 if (!XTS_PARSER (parser)->need_reparse)
961 return;
962 TSParser *treesit_parser = XTS_PARSER (parser)->parser; 1006 TSParser *treesit_parser = XTS_PARSER (parser)->parser;
963 TSTree *tree = XTS_PARSER (parser)->tree; 1007 TSTree *tree = XTS_PARSER (parser)->tree;
964 TSInput input = XTS_PARSER (parser)->input; 1008 TSInput input = XTS_PARSER (parser)->input;
@@ -978,14 +1022,17 @@ treesit_ensure_parsed (Lisp_Object parser)
978 xsignal1 (Qtreesit_parse_error, buf); 1022 xsignal1 (Qtreesit_parse_error, buf);
979 } 1023 }
980 1024
981 if (tree != NULL)
982 {
983 treesit_call_after_change_functions (tree, new_tree, parser);
984 ts_tree_delete (tree);
985 }
986
987 XTS_PARSER (parser)->tree = new_tree; 1025 XTS_PARSER (parser)->tree = new_tree;
988 XTS_PARSER (parser)->need_reparse = false; 1026 XTS_PARSER (parser)->need_reparse = false;
1027
1028 /* After-change functions should run at the very end, most crucially
1029 after need_reparse is set to false, this way if the function
1030 calls some tree-sitter function which invokes
1031 treesit_ensure_parsed again, it returns early and do not
1032 recursively call the after change functions again.
1033 (ref:notifier-inside-ensure-parsed) */
1034 treesit_call_after_change_functions (tree, new_tree, parser);
1035 ts_tree_delete (tree);
989} 1036}
990 1037
991/* This is the read function provided to tree-sitter to read from a 1038/* This is the read function provided to tree-sitter to read from a
@@ -1147,10 +1194,12 @@ treesit_query_error_to_string (TSQueryError error)
1147 1194
1148static Lisp_Object 1195static Lisp_Object
1149treesit_compose_query_signal_data (uint32_t error_offset, 1196treesit_compose_query_signal_data (uint32_t error_offset,
1150 TSQueryError error_type) 1197 TSQueryError error_type,
1198 Lisp_Object query_source)
1151{ 1199{
1152 return list3 (build_string (treesit_query_error_to_string (error_type)), 1200 return list4 (build_string (treesit_query_error_to_string (error_type)),
1153 make_fixnum (error_offset + 1), 1201 make_fixnum (error_offset + 1),
1202 query_source,
1154 build_pure_c_string ("Debug the query with `treesit-query-validate'")); 1203 build_pure_c_string ("Debug the query with `treesit-query-validate'"));
1155} 1204}
1156 1205
@@ -1192,7 +1241,8 @@ treesit_ensure_query_compiled (Lisp_Object query, Lisp_Object *signal_symbol,
1192 { 1241 {
1193 *signal_symbol = Qtreesit_query_error; 1242 *signal_symbol = Qtreesit_query_error;
1194 *signal_data = treesit_compose_query_signal_data (error_offset, 1243 *signal_data = treesit_compose_query_signal_data (error_offset,
1195 error_type); 1244 error_type,
1245 source);
1196 } 1246 }
1197 XTS_COMPILED_QUERY (query)->query = treesit_query; 1247 XTS_COMPILED_QUERY (query)->query = treesit_query;
1198 return treesit_query; 1248 return treesit_query;
@@ -1762,7 +1812,7 @@ If NODE is nil, return nil. */)
1762 return build_string (string); 1812 return build_string (string);
1763} 1813}
1764 1814
1765static TSTreeCursor treesit_cursor_helper (TSNode, Lisp_Object); 1815static bool treesit_cursor_helper (TSTreeCursor *, TSNode, Lisp_Object);
1766 1816
1767DEFUN ("treesit-node-parent", 1817DEFUN ("treesit-node-parent",
1768 Ftreesit_node_parent, Streesit_node_parent, 1, 1, 0, 1818 Ftreesit_node_parent, Streesit_node_parent, 1, 1, 0,
@@ -1778,7 +1828,10 @@ Return nil if NODE has no parent. If NODE is nil, return nil. */)
1778 1828
1779 TSNode treesit_node = XTS_NODE (node)->node; 1829 TSNode treesit_node = XTS_NODE (node)->node;
1780 Lisp_Object parser = XTS_NODE (node)->parser; 1830 Lisp_Object parser = XTS_NODE (node)->parser;
1781 TSTreeCursor cursor = treesit_cursor_helper (treesit_node, parser); 1831 TSTreeCursor cursor;
1832 if (!treesit_cursor_helper (&cursor, treesit_node, parser))
1833 return return_value;
1834
1782 if (ts_tree_cursor_goto_parent (&cursor)) 1835 if (ts_tree_cursor_goto_parent (&cursor))
1783 { 1836 {
1784 TSNode parent = ts_tree_cursor_current_node (&cursor); 1837 TSNode parent = ts_tree_cursor_current_node (&cursor);
@@ -2042,12 +2095,11 @@ Note that this function returns an immediate child, not the smallest
2042 2095
2043 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer); 2096 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer);
2044 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg; 2097 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
2045 ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos));
2046 2098
2047 treesit_check_position (pos, buf); 2099 treesit_check_position (pos, buf);
2048
2049 treesit_initialize (); 2100 treesit_initialize ();
2050 2101
2102 ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos));
2051 TSNode treesit_node = XTS_NODE (node)->node; 2103 TSNode treesit_node = XTS_NODE (node)->node;
2052 TSNode child; 2104 TSNode child;
2053 if (NILP (named)) 2105 if (NILP (named))
@@ -2078,14 +2130,14 @@ If NODE is nil, return nil. */)
2078 2130
2079 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer); 2131 struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer);
2080 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg; 2132 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
2081 ptrdiff_t byte_beg = buf_charpos_to_bytepos (buf, XFIXNUM (beg));
2082 ptrdiff_t byte_end = buf_charpos_to_bytepos (buf, XFIXNUM (end));
2083 2133
2084 treesit_check_position (beg, buf); 2134 treesit_check_position (beg, buf);
2085 treesit_check_position (end, buf); 2135 treesit_check_position (end, buf);
2086 2136
2087 treesit_initialize (); 2137 treesit_initialize ();
2088 2138
2139 ptrdiff_t byte_beg = buf_charpos_to_bytepos (buf, XFIXNUM (beg));
2140 ptrdiff_t byte_end = buf_charpos_to_bytepos (buf, XFIXNUM (end));
2089 TSNode treesit_node = XTS_NODE (node)->node; 2141 TSNode treesit_node = XTS_NODE (node)->node;
2090 TSNode child; 2142 TSNode child;
2091 if (NILP (named)) 2143 if (NILP (named))
@@ -2161,6 +2213,8 @@ See Info node `(elisp)Pattern Matching' for detailed explanation. */)
2161 return build_pure_c_string ("#equal"); 2213 return build_pure_c_string ("#equal");
2162 if (EQ (pattern, QCmatch)) 2214 if (EQ (pattern, QCmatch))
2163 return build_pure_c_string ("#match"); 2215 return build_pure_c_string ("#match");
2216 if (EQ (pattern, QCpred))
2217 return build_pure_c_string ("#pred");
2164 Lisp_Object opening_delimeter 2218 Lisp_Object opening_delimeter
2165 = build_pure_c_string (VECTORP (pattern) ? "[" : "("); 2219 = build_pure_c_string (VECTORP (pattern) ? "[" : "(");
2166 Lisp_Object closing_delimiter 2220 Lisp_Object closing_delimiter
@@ -2260,10 +2314,10 @@ treesit_predicates_for_pattern (TSQuery *query, uint32_t pattern_index)
2260 return Fnreverse (result); 2314 return Fnreverse (result);
2261} 2315}
2262 2316
2263/* Translate a capture NAME (symbol) to the text of the captured node. 2317/* Translate a capture NAME (symbol) to a node.
2264 Signals treesit-query-error if such node is not captured. */ 2318 Signals treesit-query-error if such node is not captured. */
2265static Lisp_Object 2319static Lisp_Object
2266treesit_predicate_capture_name_to_text (Lisp_Object name, 2320treesit_predicate_capture_name_to_node (Lisp_Object name,
2267 struct capture_range captures) 2321 struct capture_range captures)
2268{ 2322{
2269 Lisp_Object node = Qnil; 2323 Lisp_Object node = Qnil;
@@ -2283,6 +2337,16 @@ treesit_predicate_capture_name_to_text (Lisp_Object name,
2283 name, build_pure_c_string ("A predicate can only refer" 2337 name, build_pure_c_string ("A predicate can only refer"
2284 " to captured nodes in the " 2338 " to captured nodes in the "
2285 "same pattern")); 2339 "same pattern"));
2340 return node;
2341}
2342
2343/* Translate a capture NAME (symbol) to the text of the captured node.
2344 Signals treesit-query-error if such node is not captured. */
2345static Lisp_Object
2346treesit_predicate_capture_name_to_text (Lisp_Object name,
2347 struct capture_range captures)
2348{
2349 Lisp_Object node = treesit_predicate_capture_name_to_node (name, captures);
2286 2350
2287 struct buffer *old_buffer = current_buffer; 2351 struct buffer *old_buffer = current_buffer;
2288 set_buffer_internal (XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer)); 2352 set_buffer_internal (XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer));
@@ -2356,13 +2420,30 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures)
2356 return false; 2420 return false;
2357} 2421}
2358 2422
2359/* About predicates: I decide to hard-code predicates in C instead of 2423/* Handles predicate (#pred FN ARG...). Return true if FN returns
2360 implementing an extensible system where predicates are translated 2424 non-nil; return false otherwise. The arity of FN must match the
2361 to Lisp functions, and new predicates can be added by extending a 2425 number of ARGs */
2362 list of functions, because I really couldn't imagine any useful 2426static bool
2363 predicates besides equal and match. If we later found out that 2427treesit_predicate_pred (Lisp_Object args, struct capture_range captures)
2364 such system is indeed useful and necessary, it can be easily 2428{
2365 added. */ 2429 if (XFIXNUM (Flength (args)) < 2)
2430 xsignal2 (Qtreesit_query_error,
2431 build_pure_c_string ("Predicate `pred' requires "
2432 "at least two arguments, "
2433 "but was only given"),
2434 Flength (args));
2435
2436 Lisp_Object fn = Fintern (XCAR (args), Qnil);
2437 Lisp_Object nodes = Qnil;
2438 Lisp_Object tail = XCDR (args);
2439 FOR_EACH_TAIL (tail)
2440 nodes = Fcons (treesit_predicate_capture_name_to_node (XCAR (tail),
2441 captures),
2442 nodes);
2443 nodes = Fnreverse (nodes);
2444
2445 return !NILP (CALLN (Fapply, fn, nodes));
2446}
2366 2447
2367/* If all predicates in PREDICATES passes, return true; otherwise 2448/* If all predicates in PREDICATES passes, return true; otherwise
2368 return false. */ 2449 return false. */
@@ -2378,14 +2459,17 @@ treesit_eval_predicates (struct capture_range captures, Lisp_Object predicates)
2378 Lisp_Object fn = XCAR (predicate); 2459 Lisp_Object fn = XCAR (predicate);
2379 Lisp_Object args = XCDR (predicate); 2460 Lisp_Object args = XCDR (predicate);
2380 if (!NILP (Fstring_equal (fn, build_pure_c_string ("equal")))) 2461 if (!NILP (Fstring_equal (fn, build_pure_c_string ("equal"))))
2381 pass = treesit_predicate_equal (args, captures); 2462 pass &= treesit_predicate_equal (args, captures);
2382 else if (!NILP (Fstring_equal (fn, build_pure_c_string ("match")))) 2463 else if (!NILP (Fstring_equal (fn, build_pure_c_string ("match"))))
2383 pass = treesit_predicate_match (args, captures); 2464 pass &= treesit_predicate_match (args, captures);
2465 else if (!NILP (Fstring_equal (fn, build_pure_c_string ("pred"))))
2466 pass &= treesit_predicate_pred (args, captures);
2384 else 2467 else
2385 xsignal3 (Qtreesit_query_error, 2468 xsignal3 (Qtreesit_query_error,
2386 build_pure_c_string ("Invalid predicate"), 2469 build_pure_c_string ("Invalid predicate"),
2387 fn, build_pure_c_string ("Currently Emacs only supports" 2470 fn, build_pure_c_string ("Currently Emacs only supports"
2388 " equal and match predicate")); 2471 " equal, match, and pred"
2472 " predicate"));
2389 } 2473 }
2390 /* If all predicates passed, add captures to result list. */ 2474 /* If all predicates passed, add captures to result list. */
2391 return pass; 2475 return pass;
@@ -2546,7 +2630,7 @@ the query. */)
2546 if (treesit_query == NULL) 2630 if (treesit_query == NULL)
2547 xsignal (Qtreesit_query_error, 2631 xsignal (Qtreesit_query_error,
2548 treesit_compose_query_signal_data (error_offset, 2632 treesit_compose_query_signal_data (error_offset,
2549 error_type)); 2633 error_type, query));
2550 cursor = ts_query_cursor_new (); 2634 cursor = ts_query_cursor_new ();
2551 needs_to_free_query_and_cursor = true; 2635 needs_to_free_query_and_cursor = true;
2552 } 2636 }
@@ -2637,8 +2721,59 @@ treesit_assume_true (bool val)
2637 eassert (val == true); 2721 eassert (val == true);
2638} 2722}
2639 2723
2724/* Tries to move CURSOR to point to TARGET. END_POS is the end of
2725 TARGET. If success, return true, otherwise move CURSOR back to
2726 starting position and return false. LIMIT is the recursion
2727 limit. */
2728static bool
2729treesit_cursor_helper_1 (TSTreeCursor *cursor, TSNode *target,
2730 uint32_t end_pos, ptrdiff_t limit)
2731{
2732 if (limit <= 0)
2733 return false;
2734
2735 TSNode cursor_node = ts_tree_cursor_current_node (cursor);
2736 if (ts_node_eq (cursor_node, *target))
2737 return true;
2738
2739 if (!ts_tree_cursor_goto_first_child (cursor))
2740 return false;
2741
2742 /* Skip nodes that definitely don't contain TARGET. */
2743 while (ts_node_end_byte (cursor_node) < end_pos)
2744 {
2745 if (!ts_tree_cursor_goto_next_sibling (cursor))
2746 break;
2747 cursor_node = ts_tree_cursor_current_node (cursor);
2748 }
2749
2750 /* Go through each sibling that could contain TARGET. Because of
2751 missing nodes (their width is 0), there could be multiple
2752 siblings that could contain TARGET. */
2753 while (ts_node_start_byte (cursor_node) <= end_pos)
2754 {
2755 if (treesit_cursor_helper_1 (cursor, target, end_pos, limit - 1))
2756 return true;
2757
2758 if (!ts_tree_cursor_goto_next_sibling (cursor))
2759 break;
2760 cursor_node = ts_tree_cursor_current_node (cursor);
2761 }
2762
2763 /* Couldn't find TARGET, must be not in this subtree, move cursor
2764 back and pray that other brothers and sisters can succeed. */
2765 treesit_assume_true (ts_tree_cursor_goto_parent (cursor));
2766 return false;
2767}
2768
2640/* Create a TSTreeCursor pointing at NODE. PARSER is the lisp parser 2769/* Create a TSTreeCursor pointing at NODE. PARSER is the lisp parser
2641 that produced NODE. 2770 that produced NODE. If success, return true, otherwise return
2771 false. This function should almost always succeed, but if the parse
2772 tree is strangely too deep and exceeds the recursion limit, this
2773 function will fail and return false.
2774
2775 If this function returns true, caller needs to free CURSOR; if
2776 returns false, caller don't need to free CURSOR.
2642 2777
2643 The reason we need this instead of simply using ts_tree_cursor_new 2778 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 2779 is that we have to create the cursor on the root node and traverse
@@ -2646,56 +2781,17 @@ treesit_assume_true (bool val)
2646 Otherwise going to sibling or parent of NODE wouldn't work. 2781 Otherwise going to sibling or parent of NODE wouldn't work.
2647 2782
2648 (Wow perfect filling.) */ 2783 (Wow perfect filling.) */
2649static TSTreeCursor 2784static bool
2650treesit_cursor_helper (TSNode node, Lisp_Object parser) 2785treesit_cursor_helper (TSTreeCursor *cursor, TSNode node, Lisp_Object parser)
2651{ 2786{
2652 uint32_t end_pos = ts_node_end_byte (node); 2787 uint32_t end_pos = ts_node_end_byte (node);
2653 TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree); 2788 TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree);
2654 TSTreeCursor cursor = ts_tree_cursor_new (root); 2789 *cursor = ts_tree_cursor_new (root);
2655 TSNode cursor_node = ts_tree_cursor_current_node (&cursor); 2790 bool success = treesit_cursor_helper_1 (cursor, &node, end_pos,
2656 /* This is like treesit-node-at. We go down from the root node, 2791 treesit_recursion_limit);
2657 either to first child or next sibling, repeatedly, and finally 2792 if (!success)
2658 arrive at NODE. */ 2793 ts_tree_cursor_delete (cursor);
2659 while (!ts_node_eq (node, cursor_node)) 2794 return success;
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} 2795}
2700 2796
2701/* Move CURSOR to the next/previous sibling. FORWARD controls the 2797/* Move CURSOR to the next/previous sibling. FORWARD controls the
@@ -2957,7 +3053,7 @@ Return the first matched node, or nil if none matches. */)
2957 3053
2958 /* We use a default limit of 1000. See bug#59426 for the 3054 /* We use a default limit of 1000. See bug#59426 for the
2959 discussion. */ 3055 discussion. */
2960 ptrdiff_t the_limit = 1000; 3056 ptrdiff_t the_limit = treesit_recursion_limit;
2961 if (!NILP (limit)) 3057 if (!NILP (limit))
2962 { 3058 {
2963 CHECK_FIXNUM (limit); 3059 CHECK_FIXNUM (limit);
@@ -2968,7 +3064,10 @@ Return the first matched node, or nil if none matches. */)
2968 3064
2969 Lisp_Object parser = XTS_NODE (node)->parser; 3065 Lisp_Object parser = XTS_NODE (node)->parser;
2970 Lisp_Object return_value = Qnil; 3066 Lisp_Object return_value = Qnil;
2971 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (node)->node, parser); 3067 TSTreeCursor cursor;
3068 if (!treesit_cursor_helper (&cursor, XTS_NODE (node)->node, parser))
3069 return return_value;
3070
2972 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward), 3071 if (treesit_search_dfs (&cursor, predicate, parser, NILP (backward),
2973 NILP (all), the_limit, false)) 3072 NILP (all), the_limit, false))
2974 { 3073 {
@@ -3022,7 +3121,10 @@ always traverse leaf nodes first, then upwards. */)
3022 3121
3023 Lisp_Object parser = XTS_NODE (start)->parser; 3122 Lisp_Object parser = XTS_NODE (start)->parser;
3024 Lisp_Object return_value = Qnil; 3123 Lisp_Object return_value = Qnil;
3025 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (start)->node, parser); 3124 TSTreeCursor cursor;
3125 if (!treesit_cursor_helper (&cursor, XTS_NODE (start)->node, parser))
3126 return return_value;
3127
3026 if (treesit_search_forward (&cursor, predicate, parser, 3128 if (treesit_search_forward (&cursor, predicate, parser,
3027 NILP (backward), NILP (all))) 3129 NILP (backward), NILP (all)))
3028 { 3130 {
@@ -3130,7 +3232,7 @@ a regexp. */)
3130 3232
3131 /* We use a default limit of 1000. See bug#59426 for the 3233 /* We use a default limit of 1000. See bug#59426 for the
3132 discussion. */ 3234 discussion. */
3133 ptrdiff_t the_limit = 1000; 3235 ptrdiff_t the_limit = treesit_recursion_limit;
3134 if (!NILP (limit)) 3236 if (!NILP (limit))
3135 { 3237 {
3136 CHECK_FIXNUM (limit); 3238 CHECK_FIXNUM (limit);
@@ -3141,7 +3243,10 @@ a regexp. */)
3141 3243
3142 Lisp_Object parser = XTS_NODE (root)->parser; 3244 Lisp_Object parser = XTS_NODE (root)->parser;
3143 Lisp_Object parent = Fcons (Qnil, Qnil); 3245 Lisp_Object parent = Fcons (Qnil, Qnil);
3144 TSTreeCursor cursor = treesit_cursor_helper (XTS_NODE (root)->node, parser); 3246 TSTreeCursor cursor;
3247 if (!treesit_cursor_helper (&cursor, XTS_NODE (root)->node, parser))
3248 return Qnil;
3249
3145 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn, 3250 treesit_build_sparse_tree (&cursor, parent, predicate, process_fn,
3146 the_limit, parser); 3251 the_limit, parser);
3147 ts_tree_cursor_delete (&cursor); 3252 ts_tree_cursor_delete (&cursor);
@@ -3187,6 +3292,7 @@ syms_of_treesit (void)
3187 DEFSYM (QCanchor, ":anchor"); 3292 DEFSYM (QCanchor, ":anchor");
3188 DEFSYM (QCequal, ":equal"); 3293 DEFSYM (QCequal, ":equal");
3189 DEFSYM (QCmatch, ":match"); 3294 DEFSYM (QCmatch, ":match");
3295 DEFSYM (QCpred, ":pred");
3190 3296
3191 DEFSYM (Qnot_found, "not-found"); 3297 DEFSYM (Qnot_found, "not-found");
3192 DEFSYM (Qsymbol_error, "symbol-error"); 3298 DEFSYM (Qsymbol_error, "symbol-error");
@@ -3264,7 +3370,8 @@ then in the system default locations for dynamic libraries, in that order. */);
3264 Vtreesit_extra_load_path = Qnil; 3370 Vtreesit_extra_load_path = Qnil;
3265 3371
3266 defsubr (&Streesit_language_available_p); 3372 defsubr (&Streesit_language_available_p);
3267 defsubr (&Streesit_language_version); 3373 defsubr (&Streesit_library_abi_version);
3374 defsubr (&Streesit_language_abi_version);
3268 3375
3269 defsubr (&Streesit_parser_p); 3376 defsubr (&Streesit_parser_p);
3270 defsubr (&Streesit_node_p); 3377 defsubr (&Streesit_node_p);
diff --git a/src/w32menu.c b/src/w32menu.c
index b10239d5cc6..5f06f4c4170 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -1073,7 +1073,10 @@ is_simple_dialog (Lisp_Object contents)
1073 if (NILP (Fstring_equal (name, other))) 1073 if (NILP (Fstring_equal (name, other)))
1074 return false; 1074 return false;
1075 1075
1076 /* Check there are no more options. */ 1076 /* Check there are no more options.
1077
1078 (FIXME: Since we use MB_YESNOCANCEL, we could also consider
1079 dialogs with 3 options: Yes/No/Cancel as "simple". */
1077 options = XCDR (options); 1080 options = XCDR (options);
1078 return !(CONSP (options)); 1081 return !(CONSP (options));
1079} 1082}
@@ -1085,7 +1088,13 @@ simple_dialog_show (struct frame *f, Lisp_Object contents, Lisp_Object header)
1085 UINT type; 1088 UINT type;
1086 Lisp_Object lispy_answer = Qnil, temp = XCAR (contents); 1089 Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
1087 1090
1088 type = MB_YESNO; 1091 /* We use MB_YESNOCANCEL to allow the user the equivalent of C-g
1092 when the Yes/No question is asked vya y-or-n-p or
1093 yes-or-no-p. */
1094 if (w32_yes_no_dialog_show_cancel)
1095 type = MB_YESNOCANCEL;
1096 else
1097 type = MB_YESNO;
1089 1098
1090 /* Since we only handle Yes/No dialogs, and we already checked 1099 /* Since we only handle Yes/No dialogs, and we already checked
1091 is_simple_dialog, we don't need to worry about checking contents 1100 is_simple_dialog, we don't need to worry about checking contents
diff --git a/src/w32term.c b/src/w32term.c
index dff21489e5b..e40e4588fde 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -7696,6 +7696,7 @@ static void
7696w32_initialize (void) 7696w32_initialize (void)
7697{ 7697{
7698 HANDLE shell; 7698 HANDLE shell;
7699 BOOL caret;
7699 HRESULT (WINAPI * set_user_model) (const wchar_t * id); 7700 HRESULT (WINAPI * set_user_model) (const wchar_t * id);
7700 7701
7701 baud_rate = 19200; 7702 baud_rate = 19200;
@@ -7732,8 +7733,9 @@ w32_initialize (void)
7732 7733
7733 /* Initialize w32_use_visible_system_caret based on whether a screen 7734 /* Initialize w32_use_visible_system_caret based on whether a screen
7734 reader is in use. */ 7735 reader is in use. */
7735 if (!SystemParametersInfo (SPI_GETSCREENREADER, 0, 7736 if (SystemParametersInfo (SPI_GETSCREENREADER, 0, &caret, 0))
7736 &w32_use_visible_system_caret, 0)) 7737 w32_use_visible_system_caret = caret == TRUE;
7738 else
7737 w32_use_visible_system_caret = 0; 7739 w32_use_visible_system_caret = 0;
7738 7740
7739 any_help_event_p = 0; 7741 any_help_event_p = 0;
@@ -7923,6 +7925,11 @@ unconditionally set to nil on older systems. */);
7923 w32_use_native_image_api = 0; 7925 w32_use_native_image_api = 0;
7924#endif 7926#endif
7925 7927
7928 DEFVAR_BOOL ("w32-yes-no-dialog-show-cancel",
7929 w32_yes_no_dialog_show_cancel,
7930 doc: /* If non-nil, show Cancel button in MS-Windows GUI Yes/No dialogs. */);
7931 w32_yes_no_dialog_show_cancel = 1;
7932
7926 /* FIXME: The following variable will be (hopefully) removed 7933 /* FIXME: The following variable will be (hopefully) removed
7927 before Emacs 25.1 gets released. */ 7934 before Emacs 25.1 gets released. */
7928 7935
diff --git a/src/xdisp.c b/src/xdisp.c
index cc4c60f02da..7d1e7eeb0b9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12938,7 +12938,7 @@ clear_garbaged_frames (void)
12938 { 12938 {
12939 struct frame *f = XFRAME (frame); 12939 struct frame *f = XFRAME (frame);
12940 12940
12941 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f)) 12941 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
12942 { 12942 {
12943 if (f->resized_p 12943 if (f->resized_p
12944 /* It makes no sense to redraw a non-selected TTY 12944 /* It makes no sense to redraw a non-selected TTY
@@ -12987,7 +12987,7 @@ echo_area_display (bool update_frame_p)
12987 f = XFRAME (WINDOW_FRAME (w)); 12987 f = XFRAME (WINDOW_FRAME (w));
12988 12988
12989 /* Don't display if frame is invisible or not yet initialized. */ 12989 /* Don't display if frame is invisible or not yet initialized. */
12990 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p) 12990 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
12991 return; 12991 return;
12992 12992
12993#ifdef HAVE_WINDOW_SYSTEM 12993#ifdef HAVE_WINDOW_SYSTEM
@@ -13543,7 +13543,7 @@ prepare_menu_bars (void)
13543 TTY frames to be completely redrawn, when there 13543 TTY frames to be completely redrawn, when there
13544 are more than one of them, even though nothing 13544 are more than one of them, even though nothing
13545 should be changed on display. */ 13545 should be changed on display. */
13546 || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f)))) 13546 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13547 gui_consider_frame_title (frame); 13547 gui_consider_frame_title (frame);
13548 } 13548 }
13549 } 13549 }
@@ -14271,12 +14271,14 @@ redisplay_tab_bar (struct frame *f)
14271 frame_default_tab_bar_height = new_height; 14271 frame_default_tab_bar_height = new_height;
14272 } 14272 }
14273 14273
14274 /* If new_height or new_nrows indicate that we need to enlarge the 14274 /* If new_height or new_nrows indicate that we need to enlarge or
14275 tab-bar window, we can return right away. */ 14275 shrink the tab-bar window, we can return right away. */
14276 if (new_nrows > f->n_tab_bar_rows 14276 if (new_nrows > f->n_tab_bar_rows
14277 || (EQ (Vauto_resize_tab_bars, Qgrow_only) 14277 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14278 && !f->minimize_tab_bar_window_p 14278 && !f->minimize_tab_bar_window_p
14279 && new_height > WINDOW_PIXEL_HEIGHT (w))) 14279 && new_height > WINDOW_PIXEL_HEIGHT (w))
14280 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14281 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14280 { 14282 {
14281 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook) 14283 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14282 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height); 14284 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
@@ -16430,7 +16432,7 @@ redisplay_internal (void)
16430 { 16432 {
16431 struct frame *f = XFRAME (frame); 16433 struct frame *f = XFRAME (frame);
16432 16434
16433 if (FRAME_VISIBLE_P (f)) 16435 if (FRAME_REDISPLAY_P (f))
16434 { 16436 {
16435 ++number_of_visible_frames; 16437 ++number_of_visible_frames;
16436 /* Adjust matrices for visible frames only. */ 16438 /* Adjust matrices for visible frames only. */
@@ -16572,7 +16574,7 @@ redisplay_internal (void)
16572 && !w->update_mode_line 16574 && !w->update_mode_line
16573 && !current_buffer->clip_changed 16575 && !current_buffer->clip_changed
16574 && !current_buffer->prevent_redisplay_optimizations_p 16576 && !current_buffer->prevent_redisplay_optimizations_p
16575 && FRAME_VISIBLE_P (XFRAME (w->frame)) 16577 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16576 && !FRAME_OBSCURED_P (XFRAME (w->frame)) 16578 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16577 && !XFRAME (w->frame)->cursor_type_changed 16579 && !XFRAME (w->frame)->cursor_type_changed
16578 && !XFRAME (w->frame)->face_change 16580 && !XFRAME (w->frame)->face_change
@@ -16838,14 +16840,20 @@ redisplay_internal (void)
16838 /* Only GC scrollbars when we redisplay the whole frame. */ 16840 /* Only GC scrollbars when we redisplay the whole frame. */
16839 = f->redisplay || !REDISPLAY_SOME_P (); 16841 = f->redisplay || !REDISPLAY_SOME_P ();
16840 bool f_redisplay_flag = f->redisplay; 16842 bool f_redisplay_flag = f->redisplay;
16843
16844 /* The X error handler may have deleted that frame
16845 before we went back to retry_frame. This must come
16846 before any accesses to f->terminal. */
16847 if (!FRAME_LIVE_P (f))
16848 continue;
16849
16841 /* Mark all the scroll bars to be removed; we'll redeem 16850 /* Mark all the scroll bars to be removed; we'll redeem
16842 the ones we want when we redisplay their windows. */ 16851 the ones we want when we redisplay their windows. */
16843 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook) 16852 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
16844 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f); 16853 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
16845 16854
16846 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) 16855 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
16847 { 16856 {
16848
16849 /* Don't allow freeing images and faces for this 16857 /* Don't allow freeing images and faces for this
16850 frame as long as the frame's update wasn't 16858 frame as long as the frame's update wasn't
16851 completed. This prevents crashes when some Lisp 16859 completed. This prevents crashes when some Lisp
@@ -16870,7 +16878,7 @@ redisplay_internal (void)
16870 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook) 16878 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
16871 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f); 16879 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
16872 16880
16873 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f)) 16881 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
16874 { 16882 {
16875 /* If fonts changed on visible frame, display again. */ 16883 /* If fonts changed on visible frame, display again. */
16876 if (f->fonts_changed) 16884 if (f->fonts_changed)
@@ -16976,7 +16984,7 @@ redisplay_internal (void)
16976 } 16984 }
16977 } 16985 }
16978 } 16986 }
16979 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf)) 16987 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
16980 { 16988 {
16981 sf->inhibit_clear_image_cache = true; 16989 sf->inhibit_clear_image_cache = true;
16982 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents); 16990 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
@@ -17027,7 +17035,7 @@ redisplay_internal (void)
17027 unrequest_sigio (); 17035 unrequest_sigio ();
17028 STOP_POLLING; 17036 STOP_POLLING;
17029 17037
17030 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf)) 17038 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17031 { 17039 {
17032 if (hscroll_retries <= MAX_HSCROLL_RETRIES 17040 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17033 && hscroll_windows (selected_window)) 17041 && hscroll_windows (selected_window))
@@ -17126,7 +17134,7 @@ redisplay_internal (void)
17126 17134
17127 FOR_EACH_FRAME (tail, frame) 17135 FOR_EACH_FRAME (tail, frame)
17128 { 17136 {
17129 if (XFRAME (frame)->visible) 17137 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17130 new_count++; 17138 new_count++;
17131 } 17139 }
17132 17140
@@ -33262,7 +33270,7 @@ display_and_set_cursor (struct window *w, bool on,
33262 windows and frames; in the latter case, the frame or window may 33270 windows and frames; in the latter case, the frame or window may
33263 be in the midst of changing its size, and x and y may be off the 33271 be in the midst of changing its size, and x and y may be off the
33264 window. */ 33272 window. */
33265 if (! FRAME_VISIBLE_P (f) 33273 if (! FRAME_REDISPLAY_P (f)
33266 || vpos >= w->current_matrix->nrows 33274 || vpos >= w->current_matrix->nrows
33267 || hpos >= w->current_matrix->matrix_w) 33275 || hpos >= w->current_matrix->matrix_w)
33268 return; 33276 return;
@@ -33423,7 +33431,7 @@ gui_update_cursor (struct frame *f, bool on_p)
33423void 33431void
33424gui_clear_cursor (struct window *w) 33432gui_clear_cursor (struct window *w)
33425{ 33433{
33426 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p) 33434 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33427 update_window_cursor (w, false); 33435 update_window_cursor (w, false);
33428} 33436}
33429 33437
diff --git a/src/xfns.c b/src/xfns.c
index 668f711bdb5..1cc5aec1eb4 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4741,6 +4741,7 @@ This function is an internal primitive--use `make-frame' instead. */)
4741#endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */ 4741#endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
4742 f->output_data.x->white_relief.pixel = -1; 4742 f->output_data.x->white_relief.pixel = -1;
4743 f->output_data.x->black_relief.pixel = -1; 4743 f->output_data.x->black_relief.pixel = -1;
4744 f->output_data.x->visibility_state = VisibilityFullyObscured;
4744 4745
4745 fset_icon_name (f, gui_display_get_arg (dpyinfo, 4746 fset_icon_name (f, gui_display_get_arg (dpyinfo,
4746 parms, 4747 parms,
diff --git a/src/xterm.c b/src/xterm.c
index 8e0a97899fe..1eef8e7a724 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -21743,9 +21743,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
21743 21743
21744 case VisibilityNotify: 21744 case VisibilityNotify:
21745 f = x_top_window_to_frame (dpyinfo, event->xvisibility.window); 21745 f = x_top_window_to_frame (dpyinfo, event->xvisibility.window);
21746 if (f && (event->xvisibility.state == VisibilityUnobscured 21746
21747 || event->xvisibility.state == VisibilityPartiallyObscured)) 21747 if (f)
21748 SET_FRAME_VISIBLE (f, 1); 21748 FRAME_X_OUTPUT (f)->visibility_state = event->xvisibility.state;
21749 21749
21750 goto OTHER; 21750 goto OTHER;
21751 21751
diff --git a/src/xterm.h b/src/xterm.h
index 832ffc172b9..f06e1ec5bc6 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1290,6 +1290,11 @@ struct x_output
1290 strictly an optimization to avoid extraneous synchronizing in 1290 strictly an optimization to avoid extraneous synchronizing in
1291 some cases. */ 1291 some cases. */
1292 int root_x, root_y; 1292 int root_x, root_y;
1293
1294 /* The frame visibility state. This starts out
1295 VisibilityFullyObscured, but is set to something else in
1296 handle_one_xevent. */
1297 int visibility_state;
1293}; 1298};
1294 1299
1295enum 1300enum
@@ -1408,6 +1413,11 @@ extern void x_mark_frame_dirty (struct frame *f);
1408/* And its corresponding visual info. */ 1413/* And its corresponding visual info. */
1409#define FRAME_X_VISUAL_INFO(f) (&FRAME_DISPLAY_INFO (f)->visual_info) 1414#define FRAME_X_VISUAL_INFO(f) (&FRAME_DISPLAY_INFO (f)->visual_info)
1410 1415
1416/* Whether or not the frame is visible. Do not test this alone.
1417 Instead, use FRAME_REDISPLAY_P. */
1418#define FRAME_X_VISIBLE(f) (FRAME_X_OUTPUT (f)->visibility_state \
1419 != VisibilityFullyObscured)
1420
1411#ifdef HAVE_XRENDER 1421#ifdef HAVE_XRENDER
1412#define FRAME_X_PICTURE_FORMAT(f) FRAME_DISPLAY_INFO (f)->pict_format 1422#define FRAME_X_PICTURE_FORMAT(f) FRAME_DISPLAY_INFO (f)->pict_format
1413#define FRAME_X_PICTURE(f) ((f)->output_data.x->picture) 1423#define FRAME_X_PICTURE(f) ((f)->output_data.x->picture)