emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android 23845804a2 3/3: Merge remote-tracking branch 'origin/mas


From: Po Lu
Subject: feature/android 23845804a2 3/3: Merge remote-tracking branch 'origin/master' into feature/android
Date: Mon, 16 Jan 2023 06:50:58 -0500 (EST)

branch: feature/android
commit 23845804a2044be284a6223fc4b8d2779d0a7cc1
Merge: ad59d8986a bb67924415
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Merge remote-tracking branch 'origin/master' into feature/android
---
 doc/lispref/modes.texi                             |  14 +-
 doc/misc/htmlfontify.texi                          |  13 +-
 doc/misc/newsticker.texi                           |   9 +-
 etc/NEWS.29                                        |   6 +-
 lisp/calendar/diary-lib.el                         |   5 +-
 lisp/files.el                                      |   9 +-
 lisp/icomplete.el                                  |   4 +-
 lisp/ldefs-boot.el                                 |  79 ++++-
 lisp/ls-lisp.el                                    |  18 +-
 lisp/net/newst-ticker.el                           |  69 +++-
 lisp/net/tramp-adb.el                              |   9 +-
 lisp/net/tramp-archive.el                          |   2 +-
 lisp/net/tramp-cmds.el                             |   2 +-
 lisp/net/tramp-compat.el                           |  69 ++--
 lisp/net/tramp-gvfs.el                             |  19 +-
 lisp/net/tramp-rclone.el                           |   2 +-
 lisp/net/tramp-sh.el                               |  29 +-
 lisp/net/tramp-smb.el                              |  40 +--
 lisp/net/tramp-sudoedit.el                         |   9 +-
 lisp/net/tramp.el                                  |  62 ++--
 lisp/org/org-mouse.el                              |   4 +-
 lisp/pcomplete.el                                  |  29 +-
 lisp/progmodes/c-ts-mode.el                        | 245 +++++++++-----
 lisp/progmodes/hideif.el                           | 374 ++++++++++++++++-----
 lisp/progmodes/java-ts-mode.el                     |   3 +-
 lisp/progmodes/js.el                               |  29 ++
 lisp/progmodes/typescript-ts-mode.el               |  34 ++
 lisp/simple.el                                     |  10 +-
 lisp/sqlite-mode.el                                |   4 +
 lisp/treesit.el                                    |  13 +-
 lisp/woman.el                                      |  60 ++--
 src/ccl.c                                          |   2 +-
 src/keyboard.c                                     |   2 +-
 src/regex-emacs.c                                  |   2 +-
 .../erc/resources/networks/merge-server/track.eld  |   2 +-
 test/lisp/minibuffer-tests.el                      |   2 +-
 test/lisp/net/tramp-archive-tests.el               |   2 +-
 test/lisp/net/tramp-tests.el                       |  32 +-
 .../progmodes/c-ts-mode-resources/filling.erts     | 198 +++++++++++
 .../lisp/progmodes/c-ts-mode-resources/indent.erts | 121 ++++++-
 test/lisp/progmodes/c-ts-mode-tests.el             |   4 +
 test/manual/indent/octave.m                        |   2 +-
 42 files changed, 1226 insertions(+), 417 deletions(-)

diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index ff372edb3f..fe5eb8a1b8 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -4926,8 +4926,7 @@ the current line to @var{matcher}; if it returns 
non-@code{nil}, this
 rule is applicable.  Then Emacs passes the node to @var{anchor}, which
 returns a buffer position.  Emacs takes the column number of that
 position, adds @var{offset} to it, and the result is the indentation
-column for the current line.  @var{offset} can be an integer or a
-variable whose value is an integer.
+column for the current line.
 
 The @var{matcher} and @var{anchor} are functions, and Emacs provides
 convenient defaults for them.
@@ -4943,10 +4942,13 @@ inside a multi-line string, no node can start at that 
position, so
 @var{node} is @code{nil}.  In that case, @var{parent} would be the
 smallest node that spans that position.
 
-Emacs finds @var{bol}, @var{node} and @var{parent} and
-passes them to each @var{matcher} and @var{anchor}.  @var{matcher}
-should return non-@code{nil} if the rule is applicable, and
-@var{anchor} should return a buffer position.
+@var{matcher} should return non-@code{nil} if the rule is applicable,
+and @var{anchor} should return a buffer position.
+
+@var{offset} can be an integer, a variable whose value is an integer,
+or a function that returns an integer.  If it is a function, it is
+passed @var{node}, @var{parent}, and @var{bol}, like matchers and
+anchors.
 @end defvar
 
 @defvar treesit-simple-indent-presets
diff --git a/doc/misc/htmlfontify.texi b/doc/misc/htmlfontify.texi
index 2c96002fb1..fa45f9361a 100644
--- a/doc/misc/htmlfontify.texi
+++ b/doc/misc/htmlfontify.texi
@@ -1351,11 +1351,10 @@ Whether or not to split the index @ref{hfy-index-file} 
alphabetically
 on the first letter of each tag.  Useful when the index would otherwise
 be large and take a long time to render or be difficult to navigate.
 
-@item hfy-find-cmd
-@vindex hfy-find-cmd
-@anchor{hfy-find-cmd}
+@item hfy-exclude-file-rules
+@vindex hfy-exclude-file-rules
 
-The ``find'' command used to harvest a list of files to attempt to fontify.
+Regular expressions to exclude files which shouldn't be fontified.
 
 @item hfy-extn
 @vindex hfy-extn
@@ -1545,12 +1544,6 @@ but you should be able to override this.
 
 See: @ref{Customization}
 
-@item
-A copy of find (e.g., GNU find) that provides the @code{-path} predicate.
-
-You may be able to work around this with a suitable clever shell
-command and the customization entry: @ref{hfy-find-cmd}
-
 @item
 A copy of sed (e.g., GNU sed).
 
diff --git a/doc/misc/newsticker.texi b/doc/misc/newsticker.texi
index d71895da5d..4a0311cad4 100644
--- a/doc/misc/newsticker.texi
+++ b/doc/misc/newsticker.texi
@@ -307,11 +307,16 @@ news ticker.
 
 @findex newsticker-start-ticker
 @findex newsticker-stop-ticker
+@vindex newsticker-ticker-period
 Headlines can be displayed in the echo area, either scrolling like
 messages in a stock-quote ticker, or just changing.  This can be
 started with the command @code{newsticker-start-ticker}.  It can be
 stopped with @code{newsticker-stop-ticker}.
 
+The ticker by default runs continuously.  To only run it once, at a
+specific time interval, set the @code{newsticker-ticker-period}
+variable.
+
 
 @node Navigation
 @section Navigation
@@ -542,8 +547,10 @@ are shown in the echo area, i.e., the ``ticker''.
 @itemize
 @item
 @vindex newsticker-display-interval
+@vindex newsticker-ticker-period
 @vindex newsticker-scroll-smoothly
-@code{newsticker-ticker-interval} and
+@code{newsticker-ticker-interval},
+@code{newsticker-ticker-period}, and
 @code{newsticker-scroll-smoothly} define how headlines are shown in
 the echo area.
 @end itemize
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index ac338da71e..d1ddd0194c 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -25,11 +25,13 @@ applies, and please also update docstrings as needed.
 * Installation Changes in Emacs 29.1
 
 ---
-** Ahead-of-time native compilation can now be specified via configure.
-Use '--with-native-compilation=aot' to specify that all the Lisp files
+** Ahead-of-time native compilation can now be requested via configure.
+Use '--with-native-compilation=aot' to request that all the Lisp files
 in the Emacs tree should be natively compiled ahead of time.  (This is
 slow on most machines.)
 
+This feature existed in Emacs 28.1, but was less easy to request.
+
 +++
 ** Emacs can be built with the tree-sitter parsing library.
 This library, together with grammar libraries, provides incremental
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
index 5f1ce0aaea..946cf0e723 100644
--- a/lisp/calendar/diary-lib.el
+++ b/lisp/calendar/diary-lib.el
@@ -880,7 +880,10 @@ LIST-ONLY is non-nil, in which case it just returns the 
list."
                                    (original-date original-date))
                     (run-hooks 'diary-hook))))))
         (and temp-buff (buffer-name temp-buff) (kill-buffer temp-buff)))
-      (or d-incp (message "Preparing diary...done"))
+      (or d-incp
+          ;; Don't clobber messages displayed while preparing the diary.
+          (not (equal (current-message) "Preparing diary..."))
+          (message "Preparing diary...done"))
       diary-entries-list)))
 
 (defun diary-unhide-everything ()
diff --git a/lisp/files.el b/lisp/files.el
index d0167bf381..daa86e94d7 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7675,9 +7675,12 @@ regardless of the language.")
 (defvar insert-directory-ls-version 'unknown)
 
 (defun insert-directory-wildcard-in-dir-p (dir)
-  "Return non-nil if DIR contents a shell wildcard in the directory part.
-The return value is a cons (DIR . WILDCARDS); DIR is the
-`default-directory' in the Dired buffer, and WILDCARDS are the wildcards.
+  "Return non-nil if DIR contains shell wildcards in its parent directory part.
+The return value is a cons (DIRECTORY . WILDCARD), where DIRECTORY is the
+part of DIR up to and excluding the first component that includes
+wildcard characters, and WILDCARD is the rest of DIR's components.  The
+DIRECTORY part of the value includes the trailing slash, to indicate that
+it is a directory.
 
 Valid wildcards are `*', `?', `[abc]' and `[a-z]'."
   (let ((wildcards "[?*"))
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 9fa622017f..014f38b202 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -252,7 +252,7 @@ the default otherwise."
   "Step forward completions by one entry.
 Second entry becomes the first and can be selected with
 `icomplete-force-complete-and-exit'.
-Return non-nil iff something was stepped."
+Return non-nil if something was stepped."
   (interactive)
   (let* ((beg (icomplete--field-beg))
          (end (icomplete--field-end))
@@ -270,7 +270,7 @@ Return non-nil iff something was stepped."
   "Step backward completions by one entry.
 Last entry becomes the first and can be selected with
 `icomplete-force-complete-and-exit'.
-Return non-nil iff something was stepped."
+Return non-nil if something was stepped."
   (interactive)
   (let* ((beg (icomplete--field-beg))
          (end (icomplete--field-end))
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index c21955c3f0..4d5921582c 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -1079,10 +1079,11 @@ or a regexp (using some regexp special characters).  If 
it is a word,
 search for matches for that word as a substring.  If it is a list of words,
 search for matches for any two (or more) of those words.
 
-Note that by default this command only searches in the file specified by
-`internal-doc-file-name'; i.e., the etc/DOC file.  With \\[universal-argument] 
prefix,
-or if `apropos-do-all' is non-nil, it searches all currently defined
-documentation strings.
+Note that by default this command only searches in the functions predefined
+at Emacs startup, i.e., the primitives implemented in C or preloaded in the
+Emacs dump image.
+With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, it 
searches
+all currently defined documentation strings.
 
 Returns list of symbols and documentation found.
 
@@ -2929,6 +2930,10 @@ Major mode for editing C, powered by tree-sitter.
 (autoload 'c-ts-mode "c-ts-mode" "\
 Major mode for editing C, powered by tree-sitter.
 
+This mode is independent from the classic cc-mode.el based
+`c-mode', so configuration variables of that mode, like
+`c-basic-offset', don't affect this mode.
+
 (fn)" t)
 (autoload 'c++-ts-mode "c-ts-mode" "\
 Major mode for editing C++, powered by tree-sitter.
@@ -4114,6 +4119,22 @@ Optional argument LAX (interactively, the prefix 
argument), if
 non-nil, means also include partially matching ligatures and
 non-canonical equivalences.
 
+Each line of the display shows the equivalences in two different
+ways separated by a colon:
+
+    - as the literal character or sequence
+    - using an ASCII-only escape syntax
+
+For example, for the letter \\='r\\=', the first line is
+
+    r: ?\\N{LATIN SMALL LETTER R}
+
+which is for the requested character itself, and a later line has
+
+    ṟ: ?\\N{LATIN SMALL LETTER R}?\\N{COMBINING MACRON BELOW}
+
+which clearly shows what the constituent characters are.
+
 (fn CHAR &optional LAX)" t)
 (register-definition-prefixes "char-fold" '("char-fold-"))
 
@@ -11261,8 +11282,10 @@ For more information, see Info node `(eww) Top'.
  (defalias 'browse-web 'eww)
 (autoload 'eww-open-file "eww" "\
 Render FILE using EWW.
+If NEW-BUFFER is non-nil (interactively, the prefix arg), use a
+new buffer instead of reusing the default EWW buffer.
 
-(fn FILE)" t)
+(fn FILE &optional NEW-BUFFER)" t)
 (autoload 'eww-search-words "eww" "\
 Search the web for the text in the region.
 If region is active (and not whitespace), search the web for
@@ -22327,7 +22350,7 @@ Coloring:
 
 ;;; Generated autoloads from org/org.el
 
-(push (purecopy '(org 9 6)) package--builtin-versions)
+(push (purecopy '(org 9 6 1)) package--builtin-versions)
 (autoload 'org-babel-do-load-languages "org" "\
 Load the languages defined in `org-babel-load-languages'.
 
@@ -24511,6 +24534,7 @@ Ignores leading comment characters.
 (autoload 'pp-emacs-lisp-code "pp" "\
 Insert SEXP into the current buffer, formatted as Emacs Lisp code.
 Use the `pp-max-width' variable to control the desired line length.
+Note that this could be slow for large SEXPs.
 
 (fn SEXP)")
 (register-definition-prefixes "pp" '("pp-"))
@@ -25097,7 +25121,7 @@ Open profile FILENAME.
 
 ;;; Generated autoloads from progmodes/project.el
 
-(push (purecopy '(project 0 9 3)) package--builtin-versions)
+(push (purecopy '(project 0 9 4)) package--builtin-versions)
 (autoload 'project-current "project" "\
 Return the project instance in DIRECTORY, defaulting to `default-directory'.
 
@@ -27320,6 +27344,13 @@ it is disabled.
 ;;; Generated autoloads from progmodes/ruby-mode.el
 
 (push (purecopy '(ruby-mode 1 2)) package--builtin-versions)
+(autoload 'ruby-base-mode "ruby-mode" "\
+Generic major mode for editing Ruby.
+
+This mode is intended to be inherited by concrete major modes.
+Currently there are `ruby-mode' and `ruby-ts-mode'.
+
+(fn)" t)
 (autoload 'ruby-mode "ruby-mode" "\
 Major mode for editing Ruby code.
 
@@ -27329,6 +27360,15 @@ Major mode for editing Ruby code.
 (register-definition-prefixes "ruby-mode" '("ruby-"))
 
 
+;;; Generated autoloads from progmodes/ruby-ts-mode.el
+
+(autoload 'ruby-ts-mode "ruby-ts-mode" "\
+Major mode for editing Ruby, powered by tree-sitter.
+
+(fn)" t)
+(register-definition-prefixes "ruby-ts-mode" '("ruby-ts-"))
+
+
 ;;; Generated autoloads from ruler-mode.el
 
 (defvar-local ruler-mode nil "\
@@ -30223,7 +30263,7 @@ Return the width of STRING in pixels.
 (autoload 'string-glyph-split "subr-x" "\
 Split STRING into a list of strings representing separate glyphs.
 This takes into account combining characters and grapheme clusters:
-if compositions are enbaled, each sequence of characters composed
+if compositions are enabled, each sequence of characters composed
 on display into a single grapheme cluster is treated as a single
 indivisible unit.
 
@@ -32409,7 +32449,6 @@ Mode for displaying and reprioritizing top priority 
Todo.
 
 ;;; Generated autoloads from textmodes/toml-ts-mode.el
 
-(add-to-list 'auto-mode-alist '("\\.toml\\'" . toml-ts-mode))
 (autoload 'toml-ts-mode "toml-ts-mode" "\
 Major mode for editing TOML, powered by tree-sitter.
 
@@ -32601,7 +32640,7 @@ It must be supported by libarchive(3).")
 List of suffixes which indicate a compressed file.
 It must be supported by libarchive(3).")
 (defmacro tramp-archive-autoload-file-name-regexp nil "\
-Regular expression matching archive file names." (if (<= emacs-major-version 
26) '(concat "\\`" "\\(" ".+" "\\." (regexp-opt tramp-archive-suffixes) "\\(?:" 
"\\." (regexp-opt tramp-archive-compression-suffixes) "\\)*" "\\)" "\\(" "/" 
".*" "\\)" "\\'") `(rx bos (group (+ nonl) "." (| ,@tramp-archive-suffixes) (32 
"." (| ,@tramp-archive-compression-suffixes))) (group "/" (* nonl)) eos)))
+Regular expression matching archive file names." `(rx bos (group (+ nonl) "." 
(| ,@tramp-archive-suffixes) (32 "." (| ,@tramp-archive-compression-suffixes))) 
(group "/" (* nonl)) eos))
 (defun tramp-archive-autoload-file-name-handler (operation &rest args) "\
 Load Tramp archive file name handler, and perform OPERATION." (defvar 
tramp-archive-autoload) (let ((default-directory temporary-file-directory) 
(tramp-archive-autoload tramp-archive-enabled)) (apply 
#'tramp-autoload-file-name-handler operation args)))
 (defun tramp-register-archive-autoload-file-name-handler nil "\
@@ -32623,7 +32662,6 @@ Add archive file name handler to 
`file-name-handler-alist'." (when (and tramp-ar
 
 ;;; Generated autoloads from net/tramp-compat.el
 
- (defalias 'tramp-compat-rx #'rx)
 (register-definition-prefixes "tramp-compat" '("tramp-"))
 
 
@@ -32689,7 +32727,7 @@ Add archive file name handler to 
`file-name-handler-alist'." (when (and tramp-ar
 
 ;;; Generated autoloads from net/trampver.el
 
-(push (purecopy '(tramp 2 6 0 -1)) package--builtin-versions)
+(push (purecopy '(tramp 2 7 0 -1)) package--builtin-versions)
 (register-definition-prefixes "trampver" '("tramp-"))
 
 
@@ -32797,6 +32835,21 @@ See info node `(transient)Modifying Existing 
Transients'.
 
 ;;; Generated autoloads from treesit.el
 
+(autoload 'treesit-install-language-grammar "treesit" "\
+Build and install the tree-sitter language grammar library for LANG.
+
+Interactively, if `treesit-language-source-alist' doesn't already
+have data for building the grammar for LANG, prompt for its
+repository URL and the C/C++ compiler to use.
+
+This command requires Git, a C compiler and (sometimes) a C++ compiler,
+and the linker to be installed and on PATH.  It also requires that the
+recipe for LANG exists in `treesit-language-source-alist'.
+
+See `exec-path' for the current path where Emacs looks for
+executable programs, such as the C/C++ compiler and linker.
+
+(fn LANG)" t)
 (register-definition-prefixes "treesit" '("treesit-"))
 
 
@@ -36791,7 +36844,7 @@ If LIMIT is non-nil, then do not consider characters 
beyond LIMIT.
 
 ;;; Generated autoloads from progmodes/xref.el
 
-(push (purecopy '(xref 1 6 0)) package--builtin-versions)
+(push (purecopy '(xref 1 6 1)) package--builtin-versions)
 (autoload 'xref-find-backend "xref")
 (define-obsolete-function-alias 'xref-pop-marker-stack #'xref-go-back "29.1")
 (autoload 'xref-go-back "xref" "\
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
index 217bebcfcb..81ff14932c 100644
--- a/lisp/ls-lisp.el
+++ b/lisp/ls-lisp.el
@@ -482,8 +482,22 @@ not contain `d', so that a full listing is expected."
       (if (not dir-wildcard)
           (funcall orig-fun dir-or-list switches)
         (let* ((default-directory (car dir-wildcard))
-               (files (file-expand-wildcards (cdr dir-wildcard)))
+               (wildcard (cdr dir-wildcard))
+               (files (file-expand-wildcards wildcard))
                (dir (car dir-wildcard)))
+          ;; When the wildcard ends in a slash, file-expand-wildcards
+          ;; returns nil; fix that by treating the wildcards as
+          ;; specifying only directories whose names match the
+          ;; widlcard.
+          (if (and (null files)
+                   (directory-name-p wildcard))
+              (setq files
+                    (delq nil
+                          (mapcar (lambda (fname)
+                                   (if (file-accessible-directory-p fname)
+                                        fname))
+                                 (file-expand-wildcards
+                                   (directory-file-name wildcard))))))
           (if files
               (let ((inhibit-read-only t)
                     (buf
@@ -494,7 +508,7 @@ not contain `d', so that a full listing is expected."
                     (dired-goto-next-file)
                     (forward-line 0)
                     (insert "  wildcard " (cdr dir-wildcard) "\n"))))
-            (user-error "No files matching regexp")))))))
+            (user-error "No files matching wildcard")))))))
 
 (advice-add 'dired :around #'ls-lisp--dired)
 
diff --git a/lisp/net/newst-ticker.el b/lisp/net/newst-ticker.el
index 5477ad946b..064b72f02c 100644
--- a/lisp/net/newst-ticker.el
+++ b/lisp/net/newst-ticker.el
@@ -44,8 +44,10 @@
   "Last message that the newsticker displayed.")
 (defvar newsticker--scrollable-text ""
   "The text which is scrolled smoothly in the echo area.")
+(defvar newsticker--ticker-period-timer nil
+  "Timer for newsticker ticker display.")
 (defvar newsticker--ticker-timer nil
-  "Timer for newsticker ticker.")
+  "Timer for newsticker ticker scrolling.")
 
 ;;;###autoload
 (defun newsticker-ticker-running-p ()
@@ -77,7 +79,7 @@ value effective."
 
 (defcustom newsticker-ticker-interval
   0.3
-  "Time interval for displaying news items in the echo area (seconds).
+  "Time interval for scrolling news items in the echo area (seconds).
 If equal or less than 0 no messages are shown in the echo area.  For
 smooth display (see `newsticker-scroll-smoothly') a value of 0.3 seems
 reasonable.  For non-smooth display a value of 10 is a good starting
@@ -86,6 +88,17 @@ point."
   :set #'newsticker--set-customvar-ticker
   :group 'newsticker-ticker)
 
+(defcustom newsticker-ticker-period
+  0
+  "Time interval for displaying news items in the echo area (seconds).
+If equal or less than 0 messages are shown continuously.  In order not
+to miss new items, a value of equal or less than the shortest feed
+retrieval interval (or the global `newsticker-retrieval-interval`) is
+recommended."
+  :type 'number
+  :set #'newsticker--set-customvar-ticker
+  :group 'newsticker-ticker)
+
 (defcustom newsticker-scroll-smoothly
   t
   "Decides whether to flash or scroll news items.
@@ -129,9 +142,16 @@ If t the echo area will not show obsolete items.  See also
   "Called from the display timer.
 This function calls a display function, according to the variable
 `newsticker-scroll-smoothly'."
-  (if newsticker-scroll-smoothly
-      (newsticker--display-scroll)
-    (newsticker--display-jump)))
+  (when (not newsticker--ticker-timer)
+      (if newsticker-scroll-smoothly
+       (setq newsticker--ticker-timer
+             (run-at-time 1
+                          newsticker-ticker-interval
+                          #'newsticker--display-scroll))
+     (setq newsticker--ticker-timer
+           (run-at-time nil
+                        newsticker-ticker-interval
+                        #'newsticker--display-jump)))))
 
 (defsubst newsticker--echo-area-clean-p ()
   "Check whether somebody is using the echo area / minibuffer.
@@ -149,7 +169,12 @@ there is another message displayed or the minibuffer is 
active."
     (when (newsticker--echo-area-clean-p)
       (setq newsticker--item-position (1+ newsticker--item-position))
       (when (>= newsticker--item-position (length newsticker--item-list))
-        (setq newsticker--item-position 0))
+        (setq newsticker--item-position 0)
+        (when (> newsticker-ticker-period 0)
+          (cancel-timer newsticker--ticker-timer)
+          (setq newsticker--ticker-timer nil)
+          (run-at-time newsticker-ticker-interval nil
+                       (lambda () (message "")))))
       (setq newsticker--prev-message
             (nth newsticker--item-position newsticker--item-list))
       (message "%s" newsticker--prev-message))))
@@ -192,7 +217,12 @@ there is another message displayed or the minibuffer is 
active."
         (setq newsticker--prev-message subtext)
         (setq newsticker--item-position (1+ i))
         (when (>= newsticker--item-position l)
-          (setq newsticker--item-position 0))))))
+          (setq newsticker--item-position 0)
+          (when (> newsticker-ticker-period 0)
+            (cancel-timer newsticker--ticker-timer)
+            (setq newsticker--ticker-timer nil)
+            (run-at-time newsticker-ticker-interval nil
+                         (lambda () (message "")))))))))
 
 ;;;###autoload
 (defun newsticker-start-ticker ()
@@ -200,19 +230,26 @@ there is another message displayed or the minibuffer is 
active."
 Start display timer for the actual ticker if wanted and not
 running already."
   (interactive)
-  (if (and (> newsticker-ticker-interval 0)
-           (not newsticker--ticker-timer))
-      (setq newsticker--ticker-timer
-            (run-at-time newsticker-ticker-interval
-                         newsticker-ticker-interval
-                         #'newsticker--display-tick))))
+  (when (and (> newsticker-ticker-interval 0)
+             (not newsticker--ticker-period-timer)
+             (not newsticker--ticker-timer))
+      (if (> newsticker-ticker-period 0)
+          (setq newsticker--ticker-period-timer
+                (run-at-time nil
+                             newsticker-ticker-period
+                             #'newsticker--display-tick))
+        (newsticker--display-tick))))
 
 (defun newsticker-stop-ticker ()
   "Stop newsticker's ticker (but not the news retrieval)."
   (interactive)
-  (when newsticker--ticker-timer
-    (cancel-timer newsticker--ticker-timer)
-    (setq newsticker--ticker-timer nil)))
+  (progn
+    (when newsticker--ticker-timer
+      (cancel-timer newsticker--ticker-timer)
+      (setq newsticker--ticker-timer nil))
+    (when newsticker--ticker-period-timer
+      (cancel-timer newsticker--ticker-period-timer)
+      (setq newsticker--ticker-period-timer nil))))
 
 ;; ======================================================================
 ;;; Manipulation of ticker text
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 493a9fb39a..29b9f894ec 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -1078,11 +1078,12 @@ E.g. a host name \"192.168.1.1#5555\" returns 
\"192.168.1.1:5555\"
              (format "%s:%s" host port))
             ;; An empty host name shall be mapped as well, when there
             ;; is exactly one entry in `devices'.
-            ((and (zerop (length host)) (= (length devices) 1))
+            ((and (tramp-string-empty-or-nil-p host)
+                  (tramp-compat-length= devices 1))
              (car devices))
             ;; Try to connect device.
             ((and tramp-adb-connect-if-not-connected
-                  (not (zerop (length host)))
+                  (tramp-compat-length> host 0)
                   (tramp-adb-execute-adb-command
                     vec "connect"
                     (tramp-compat-string-replace
@@ -1099,7 +1100,7 @@ E.g. a host name \"192.168.1.1#5555\" returns 
\"192.168.1.1:5555\"
   "Execute an adb command.
 Insert the result into the connection buffer.  Return nil on
 error and non-nil on success."
-  (when (and (> (length (tramp-file-name-host vec)) 0)
+  (when (and (tramp-compat-length> (tramp-file-name-host vec) 0)
             ;; The -s switch is only available for ADB device commands.
             (not (member (car args) '("connect" "disconnect"))))
     (setq args (append (list "-s" (tramp-adb-get-device vec)) args)))
@@ -1226,7 +1227,7 @@ connection if a previous connection has died for some 
reason."
     (unless (process-live-p p)
       (save-match-data
        (when (and p (processp p)) (delete-process p))
-       (if (zerop (length device))
+       (if (tramp-string-empty-or-nil-p device)
            (tramp-error vec 'file-error "Device %s not connected" host))
        (with-tramp-progress-reporter vec 3 "Opening adb shell connection"
          (let* ((coding-system-for-read 'utf-8-dos) ; Is this correct?
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index a2add1ed73..3b1d568c12 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -598,7 +598,7 @@ offered."
 (defun tramp-archive-handle-directory-file-name (directory)
   "Like `directory-file-name' for file archives."
   (with-parsed-tramp-archive-file-name directory nil
-    (if (and (not (zerop (length localname)))
+    (if (and (tramp-compat-length> localname 0)
             (eq (aref localname (1- (length localname))) ?/)
             (not (string= localname "/")))
        (substring directory 0 -1)
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index dc967dccf6..6627ef47ee 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -127,7 +127,7 @@ When called interactively, a Tramp connection has to be 
selected."
                 (or (not keep-processes)
                     (eq key (tramp-get-process vec))))
        (tramp-flush-connection-properties key)
-       (delete-process key)))
+       (ignore-errors (delete-process key))))
 
     ;; Remove buffers.
     (dolist
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 6a2654ee47..95d22c4e14 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -178,6 +178,48 @@ Add the extension of F, if existing."
                          (car components))
                 (cdr components)))))))
 
+;; Function `replace-regexp-in-region' is new in Emacs 28.1.
+(defalias 'tramp-compat-replace-regexp-in-region
+  (if (fboundp 'replace-regexp-in-region)
+      #'replace-regexp-in-region
+    (lambda (regexp replacement &optional start end)
+      (if start
+         (when (< start (point-min))
+            (error "Start before start of buffer"))
+       (setq start (point)))
+      (if end
+         (when (> end (point-max))
+            (error "End after end of buffer"))
+       (setq end (point-max)))
+      (save-excursion
+       (let ((matches 0)
+              (case-fold-search nil))
+         (goto-char start)
+         (while (re-search-forward regexp end t)
+            (replace-match replacement t)
+            (setq matches (1+ matches)))
+         (and (not (zerop matches))
+               matches))))))
+
+;; `length<', `length>' and `length=' are added to Emacs 28.1.
+(defalias 'tramp-compat-length<
+  (if (fboundp 'length<)
+      #'length<
+    (lambda (sequence length)
+      (< (length sequence) length))))
+
+(defalias 'tramp-compat-length>
+  (if (fboundp 'length>)
+      #'length>
+    (lambda (sequence length)
+      (> (length sequence) length))))
+
+(defalias 'tramp-compat-length=
+  (if (fboundp 'length=)
+      #'length=
+    (lambda (sequence length)
+      (= (length sequence) length))))
+
 ;; `permission-denied' is introduced in Emacs 29.1.
 (defconst tramp-permission-denied
   (if (get 'permission-denied 'error-conditions) 'permission-denied 
'file-error)
@@ -205,7 +247,7 @@ Add the extension of F, if existing."
       #'take
     (lambda (n list)
       (when (and (natnump n) (> n 0))
-       (if (>= n (length list))
+       (if (tramp-compat-length< list n)
            list (butlast list (- (length list) n)))))))
 
 ;; Function `ntake' is new in Emacs 29.1.
@@ -214,7 +256,7 @@ Add the extension of F, if existing."
       #'ntake
     (lambda (n list)
       (when (and (natnump n) (> n 0))
-       (if (>= n (length list))
+       (if (tramp-compat-length< list n)
            list (nbutlast list (- (length list) n)))))))
 
 ;; Function `string-equal-ignore-case' is new in Emacs 29.1.
@@ -234,29 +276,6 @@ Add the extension of F, if existing."
       (autoload 'netrc-parse "netrc")
       (netrc-parse file))))
 
-;; Function `replace-regexp-in-region' is new in Emacs 28.1.
-(defalias 'tramp-compat-replace-regexp-in-region
-  (if (fboundp 'replace-regexp-in-region)
-      #'replace-regexp-in-region
-    (lambda (regexp replacement &optional start end)
-      (if start
-         (when (< start (point-min))
-            (error "Start before start of buffer"))
-       (setq start (point)))
-      (if end
-         (when (> end (point-max))
-            (error "End after end of buffer"))
-       (setq end (point-max)))
-      (save-excursion
-       (let ((matches 0)
-              (case-fold-search nil))
-         (goto-char start)
-         (while (re-search-forward regexp end t)
-            (replace-match replacement t)
-            (setq matches (1+ matches)))
-         (and (not (zerop matches))
-               matches))))))
-
 (dolist (elt (all-completions "tramp-compat-" obarray 'functionp))
   (put (intern elt) 'tramp-suppress-trace t))
 
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index cca7a5fe24..ea774d0b9b 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1154,7 +1154,8 @@ file names."
   ;; If DIR is not given, use DEFAULT-DIRECTORY or "/".
   (setq dir (or dir default-directory "/"))
   ;; Handle empty NAME.
-  (when (zerop (length name)) (setq name "."))
+  (when (string-empty-p name)
+    (setq name "."))
   ;; Unless NAME is absolute, concat DIR and NAME.
   (unless (file-name-absolute-p name)
     (setq name (tramp-compat-file-name-concat dir name)))
@@ -1169,7 +1170,7 @@ file names."
        (let ((uname (match-string 1 localname))
              (fname (match-string 2 localname))
              hname)
-         (when (zerop (length uname))
+         (when (tramp-string-empty-or-nil-p uname)
            (setq uname user))
          (when (setq hname (tramp-get-home-directory v uname))
            (setq localname (concat hname fname)))))
@@ -1530,7 +1531,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
            'file-notify-callback (list proc action file file1)))))
 
     ;; Save rest of the string.
-    (when (zerop (length string)) (setq string nil))
+    (when (string-empty-p string) (setq string nil))
     (when string (tramp-message proc 10 "Rest string:\n%s" string))
     (process-put proc 'rest-string string)))
 
@@ -1611,7 +1612,7 @@ VEC or USER, or if there is no home directory, return 
nil."
   (let ((localname (tramp-get-connection-property vec "default-location"))
        result)
     (cond
-     ((zerop (length localname))
+     ((tramp-string-empty-or-nil-p localname)
       (tramp-get-connection-property (tramp-get-process vec) "share"))
      ;; Google-drive.
      ((not (string-prefix-p "/" localname))
@@ -1743,11 +1744,11 @@ a downcased host name only."
 
     (condition-case nil
        (with-parsed-tramp-file-name filename l
-         (when (and (zerop (length user))
+         (when (and (tramp-string-empty-or-nil-p user)
                     (not
                      (zerop (logand flags tramp-gvfs-password-need-username))))
            (setq user (read-string "User name: ")))
-         (when (and (zerop (length domain))
+         (when (and (tramp-string-empty-or-nil-p domain)
                     (not
                      (zerop (logand flags tramp-gvfs-password-need-domain))))
            (setq domain (read-string "Domain name: ")))
@@ -2184,7 +2185,7 @@ connection if a previous connection has died for some 
reason."
 
       (with-tramp-progress-reporter
          vec 3
-         (if (zerop (length user))
+         (if (tramp-string-empty-or-nil-p user)
              (format "Opening connection for %s using %s" host method)
            (format "Opening connection for %s@%s using %s" user host method))
 
@@ -2234,7 +2235,7 @@ connection if a previous connection has died for some 
reason."
        (with-timeout
            ((or (tramp-get-method-parameter vec 'tramp-connection-timeout)
                 tramp-connection-timeout)
-            (if (zerop (length (tramp-file-name-user vec)))
+            (if (tramp-string-empty-or-nil-p (tramp-file-name-user vec))
                 (tramp-error
                  vec 'file-error
                  "Timeout reached mounting %s using %s" host method)
@@ -2413,7 +2414,7 @@ VEC is used only for traces."
     ;; Adapt default host name, supporting /mtp:: when possible.
     (setq tramp-default-host-alist
          (append
-          `(("mtp" nil ,(if (= (length devices) 1) (car devices) "")))
+          `(("mtp" nil ,(if (tramp-compat-length= devices 1) (car devices) 
"")))
           (delete
            (assoc "mtp" tramp-default-host-alist)
            tramp-default-host-alist)))))
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 4018fa3aa2..b28f9f6495 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -361,7 +361,7 @@ connection if a previous connection has died for some 
reason."
 
   (let ((host (tramp-file-name-host vec)))
     (when (rassoc `(,host) (tramp-rclone-parse-device-names nil))
-      (if (zerop (length host))
+      (if (tramp-string-empty-or-nil-p host)
          (tramp-error vec 'file-error "Storage %s not connected" host))
       ;; We need a process bound to the connection buffer.  Therefore,
       ;; we create a dummy process.  Maybe there is a better solution?
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 4647600071..acbb6aea13 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1736,7 +1736,7 @@ ID-FORMAT valid values are `string' and `integer'."
     ;; Sometimes, when a connection is not established yet, it is
     ;; desirable to return t immediately for "/method:foo:".  It can
     ;; be expected that this is always a directory.
-    (or (zerop (length localname))
+    (or (tramp-string-empty-or-nil-p localname)
        (with-tramp-file-property v localname "file-directory-p"
          (if-let
              ((truename (tramp-get-file-property v localname "file-truename"))
@@ -2349,7 +2349,7 @@ The method used must be an out-of-band method."
         copy-program copy-args copy-env copy-keep-date listener spec
         options source target remote-copy-program remote-copy-args p)
 
-    (if (and v1 v2 (zerop (length (tramp-scp-direct-remote-copying v1 v2))))
+    (if (and v1 v2 (string-empty-p (tramp-scp-direct-remote-copying v1 v2)))
 
        ;; Both are Tramp files.  We cannot use direct remote copying.
        (let* ((dir-flag (file-directory-p filename))
@@ -2684,9 +2684,9 @@ The method used must be an out-of-band method."
                   (tramp-get-ls-command v)
                   switches
                   (if (or wildcard
-                          (zerop (length
-                                  (tramp-run-real-handler
-                                   #'file-name-nondirectory (list 
localname)))))
+                          (tramp-string-empty-or-nil-p
+                           (tramp-run-real-handler
+                            #'file-name-nondirectory (list localname))))
                       ""
                     (tramp-shell-quote-argument
                      (tramp-run-real-handler
@@ -2803,7 +2803,8 @@ the result will be a local, non-Tramp, file name."
   ;; If DIR is not given, use `default-directory' or "/".
   (setq dir (or dir default-directory "/"))
   ;; Handle empty NAME.
-  (when (zerop (length name)) (setq name "."))
+  (when (string-empty-p name)
+    (setq name "."))
   ;; On MS Windows, some special file names are not returned properly
   ;; by `file-name-absolute-p'.  If `tramp-syntax' is `simplified',
   ;; there could be the false positive "/:".
@@ -2838,7 +2839,7 @@ the result will be a local, non-Tramp, file name."
            ;; the default user name for tilde expansion is not
            ;; appropriate either, because ssh and companions might
            ;; use a user name from the config file.
-           (when (and (zerop (length uname))
+           (when (and (tramp-string-empty-or-nil-p uname)
                       (string-match-p (rx bos "su" (? "do") eos) method))
              (setq uname user))
            (when (setq hname (tramp-get-home-directory v uname))
@@ -2939,7 +2940,7 @@ implementation will be used."
                 (heredoc (and (not (bufferp stderr))
                               (stringp program)
                               (string-match-p (rx "sh" eol) program)
-                              (= (length args) 2)
+                              (tramp-compat-length= args 2)
                               (string-equal "-c" (car args))
                               ;; Don't if there is a quoted string.
                               (not
@@ -2949,7 +2950,7 @@ implementation will be used."
                 ;; When PROGRAM is nil, we just provide a tty.
                 (args (if (not heredoc) args
                         (let ((i 250))
-                          (while (and (< i (length (cadr args)))
+                          (while (and (not (tramp-compat-length< (cadr args) 
i))
                                       (string-match " " (cadr args) i))
                             (setcdr
                              args
@@ -3931,7 +3932,7 @@ Fall back to normal file name handler if no Tramp handler 
exists."
     ;; Save rest of the string.
     (while (string-match (rx bol "\n") string)
       (setq string (replace-match "" nil nil string)))
-    (when (zerop (length string)) (setq string nil))
+    (when (string-empty-p string) (setq string nil))
     (when string (tramp-message proc 10 "Rest string:\n%s" string))
     (process-put proc 'rest-string string)))
 
@@ -4176,7 +4177,7 @@ variable PATH."
             'noerror)))
        tmpfile chunk chunksize)
     (tramp-message vec 5 "Setting $PATH environment variable")
-    (if (< (length command) pipe-buf)
+    (if (tramp-compat-length< command pipe-buf)
        (tramp-send-command vec command)
       ;; Use a temporary file.  We cannot use `write-region' because
       ;; setting the remote path happens in the early connection
@@ -4565,7 +4566,7 @@ process to set up.  VEC specifies the connection."
 
     ;; Set `remote-tty' process property.
     (let ((tty (tramp-send-command-and-read vec "echo \\\"`tty`\\\"" 
'noerror)))
-      (unless (zerop (length tty))
+      (unless (string-empty-p tty)
        (process-put proc 'remote-tty tty)
        (tramp-set-connection-property proc "remote-tty" tty)))
 
@@ -5138,7 +5139,7 @@ connection if a previous connection has died for some 
reason."
        (unless (process-live-p p)
          (with-tramp-progress-reporter
              vec 3
-             (if (zerop (length (tramp-file-name-user vec)))
+             (if (tramp-string-empty-or-nil-p (tramp-file-name-user vec))
                  (format "Opening connection %s for %s using %s"
                          process-name
                          (tramp-file-name-host vec)
@@ -5511,7 +5512,7 @@ raises an error."
     (cond
      ((tramp-get-method-parameter vec 'tramp-remote-copy-program)
       localname)
-     ((zerop (length user)) (format "%s:%s" host localname))
+     ((tramp-string-empty-or-nil-p user) (format "%s:%s" host localname))
      (t (format "%s@%s:%s" user host localname)))))
 
 (defun tramp-method-out-of-band-p (vec size)
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index d6f3cca973..b3f0344f81 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -487,9 +487,9 @@ arguments to pass to the OPERATION."
                       (args      (list (concat "//" host "/" share) "-E"))
                       (options   tramp-smb-options))
 
-                 (if (not (zerop (length user)))
-                     (setq args (append args (list "-U" user)))
-                   (setq args (append args (list "-N"))))
+                 (if (tramp-string-empty-or-nil-p user)
+                     (setq args (append args (list "-N")))
+                   (setq args (append args (list "-U" user))))
 
                  (when domain (setq args (append args (list "-W" domain))))
                  (when port   (setq args (append args (list "-p" port))))
@@ -712,7 +712,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
   ;; If DIR is not given, use DEFAULT-DIRECTORY or "/".
   (setq dir (or dir default-directory "/"))
   ;; Handle empty NAME.
-  (when (zerop (length name)) (setq name "."))
+  (when (string-empty-p name)
+    (setq name "."))
   ;; Unless NAME is absolute, concat DIR and NAME.
   (unless (file-name-absolute-p name)
     (setq name (tramp-compat-file-name-concat dir name)))
@@ -727,7 +728,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
        (let ((uname (match-string 1 localname))
              (fname (match-string 2 localname))
              hname)
-         (when (zerop (length uname))
+         (when (tramp-string-empty-or-nil-p uname)
            (setq uname user))
          (when (setq hname (tramp-get-home-directory v uname))
            (setq localname (concat hname fname)))))
@@ -781,9 +782,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                 (args      (list (concat "//" host "/" share) "-E"))
                 (options   tramp-smb-options))
 
-           (if (not (zerop (length user)))
-               (setq args (append args (list "-U" user)))
-             (setq args (append args (list "-N"))))
+           (if (tramp-string-empty-or-nil-p user)
+               (setq args (append args (list "-N")))
+             (setq args (append args (list "-U" user))))
 
            (when domain (setq args (append args (list "-W" domain))))
            (when port   (setq args (append args (list "-p" port))))
@@ -1071,7 +1072,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (setq entries
                (delq
                 nil
-                (if (or wildcard (zerop (length base)))
+                (if (or wildcard (string-empty-p base))
                     ;; Check for matching entries.
                     (mapcar
                      (lambda (x)
@@ -1096,7 +1097,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (when (tramp-compat-string-search "F" switches)
            (mapc
             (lambda (x)
-              (unless (zerop (length (car x)))
+              (unless (string-empty-p (car x))
                 (cond
                  ((char-equal ?d (string-to-char (nth 1 x)))
                   (setcar x (concat (car x) "/")))
@@ -1116,7 +1117,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          ;; Print entries.
          (mapc
           (lambda (x)
-            (unless (zerop (length (nth 0 x)))
+            (unless (string-empty-p (nth 0 x))
               (let ((attr
                      (when (tramp-smb-get-stat-capability v)
                        (ignore-errors
@@ -1409,9 +1410,9 @@ component is used as the target of the symlink."
                                 "\n" "," acl-string)))
               (options   tramp-smb-options))
 
-         (if (not (zerop (length user)))
-             (setq args (append args (list "-U" user)))
-           (setq args (append args (list "-N"))))
+         (if (tramp-string-empty-or-nil-p user)
+             (setq args (append args (list "-N")))
+           (setq args (append args (list "-U" user))))
 
          (when domain (setq args (append args (list "-W" domain))))
          (when port   (setq args (append args (list "-p" port))))
@@ -1561,7 +1562,7 @@ If USER is a string, return its home directory instead of 
the
 user identified by VEC.  If there is no user specified in either
 VEC or USER, or if there is no home directory, return nil."
   (let ((user (or user (tramp-file-name-user vec))))
-    (unless (zerop (length user))
+    (unless (tramp-string-empty-or-nil-p user)
       (concat "/" user))))
 
 (defun tramp-smb-handle-write-region
@@ -1959,9 +1960,9 @@ If ARGUMENT is non-nil, use it as argument for
           (t
            (setq args (list "-g" "-L" host ))))
 
-         (if (not (zerop (length user)))
-             (setq args (append args (list "-U" user)))
-           (setq args (append args (list "-N"))))
+         (if (tramp-string-empty-or-nil-p user)
+             (setq args (append args (list "-N")))
+           (setq args (append args (list "-U" user))))
 
          (when domain (setq args (append args (list "-W" domain))))
          (when port   (setq args (append args (list "-p" port))))
@@ -1976,7 +1977,8 @@ If ARGUMENT is non-nil, use it as argument for
          (with-tramp-progress-reporter
              vec 3
              (format "Opening connection for //%s%s/%s"
-                     (if (not (zerop (length user))) (concat user "@") "")
+                     (if (tramp-string-empty-or-nil-p user)
+                         "" (concat user "@"))
                      host (or share ""))
 
            (let* (coding-system-for-read
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 2660dbb1fa..ce080918e0 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -363,7 +363,8 @@ the result will be a local, non-Tramp, file name."
   ;; If DIR is not given, use `default-directory' or "/".
   (setq dir (or dir default-directory "/"))
   ;; Handle empty NAME.
-  (when (zerop (length name)) (setq name "."))
+  (when (string-empty-p name)
+    (setq name "."))
   ;; Unless NAME is absolute, concat DIR and NAME.
   (unless (file-name-absolute-p name)
     (setq name (tramp-compat-file-name-concat dir name)))
@@ -374,7 +375,7 @@ the result will be a local, non-Tramp, file name."
       ;; Tilde expansion if necessary.  We cannot accept "~/", because
       ;; under sudo "~/" is expanded to the local user home directory
       ;; but to the root home directory.
-      (when (zerop (length localname))
+      (when (tramp-string-empty-or-nil-p localname)
        (setq localname "~"))
       (unless (file-name-absolute-p localname)
        (setq localname (format "~%s/%s" user localname)))
@@ -383,7 +384,7 @@ the result will be a local, non-Tramp, file name."
        (let ((uname (match-string 1 localname))
              (fname (match-string 2 localname))
              hname)
-         (when (zerop (length uname))
+         (when (tramp-string-empty-or-nil-p uname)
            (setq uname user))
          (when (setq hname (tramp-get-home-directory v uname))
            (setq localname (concat hname fname)))))
@@ -471,7 +472,7 @@ the result will be a local, non-Tramp, file name."
      (with-tramp-file-property v localname "file-name-all-completions"
        (tramp-sudoedit-send-command
        v "ls" "-a1" "--quoting-style=literal" "--show-control-chars"
-       (if (zerop (length localname))
+       (if (tramp-string-empty-or-nil-p localname)
            "" (file-name-unquote localname)))
        (mapcar
        (lambda (f)
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index b8475b7cb4..169cf1982b 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1630,7 +1630,7 @@ This is USER, if non-nil.  Otherwise, do a lookup in
 This is HOST, if non-nil.  Otherwise, do a lookup in
 `tramp-default-host-alist' and `tramp-default-host'."
   (let ((result
-        (or (and (> (length host) 0) host)
+        (or (and (tramp-compat-length> host 0) host)
             (let ((choices tramp-default-host-alist)
                   lhost item)
               (while choices
@@ -1642,7 +1642,7 @@ This is HOST, if non-nil.  Otherwise, do a lookup in
               lhost)
             tramp-default-host)))
     ;; We must mark, whether a default value has been used.
-    (if (or (> (length host) 0) (null result))
+    (if (or (tramp-compat-length> host 0) (null result))
        result
       (propertize result 'tramp-default t))))
 
@@ -1748,14 +1748,18 @@ See `tramp-dissect-file-name' for details."
 
 (put #'tramp-dissect-hop-name 'tramp-suppress-trace t)
 
+(defsubst tramp-string-empty-or-nil-p (string)
+  "Check whether STRING is empty or nil."
+  (or (null string) (string= string "")))
+
 (defun tramp-buffer-name (vec)
   "A name for the connection buffer VEC."
   (let ((method (tramp-file-name-method vec))
        (user-domain (tramp-file-name-user-domain vec))
        (host-port (tramp-file-name-host-port vec)))
-    (if (not (zerop (length user-domain)))
-       (format "*tramp/%s %s@%s*" method user-domain host-port)
-      (format "*tramp/%s %s*" method host-port))))
+    (if (tramp-string-empty-or-nil-p user-domain)
+       (format "*tramp/%s %s*" method host-port)
+      (format "*tramp/%s %s@%s*" method user-domain host-port))))
 
 (put #'tramp-buffer-name 'tramp-suppress-trace t)
 
@@ -1800,23 +1804,23 @@ the form (METHOD USER DOMAIN HOST PORT LOCALNAME 
&optional HOP)."
              hop (nth 6 args))))
 
     ;; Unless `tramp-syntax' is `simplified', we need a method.
-    (when (and (not (zerop (length tramp-postfix-method-format)))
-              (zerop (length method)))
+    (when (and (not (string-empty-p tramp-postfix-method-format))
+              (tramp-string-empty-or-nil-p method))
       (signal 'wrong-type-argument (list #'stringp method)))
     (concat tramp-prefix-format hop
-           (unless (zerop (length tramp-postfix-method-format))
+           (unless (string-empty-p tramp-postfix-method-format)
              (concat method tramp-postfix-method-format))
            user
-           (unless (zerop (length domain))
+           (unless (tramp-string-empty-or-nil-p domain)
              (concat tramp-prefix-domain-format domain))
-           (unless (zerop (length user))
+           (unless (tramp-string-empty-or-nil-p user)
              tramp-postfix-user-format)
            (when host
              (if (string-match-p tramp-ipv6-regexp host)
                  (concat
                   tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
                host))
-           (unless (zerop (length port))
+           (unless (tramp-string-empty-or-nil-p port)
              (concat tramp-prefix-port-format port))
            tramp-postfix-host-format
            localname)))
@@ -1840,12 +1844,12 @@ the form (METHOD USER DOMAIN HOST PORT LOCALNAME 
&optional HOP)."
 It must not be a complete Tramp file name, but as long as there are
 necessary only.  This function will be used in file name completion."
   (concat tramp-prefix-format
-         (unless (or (zerop (length method))
-                      (zerop (length tramp-postfix-method-format)))
+         (unless (or (tramp-string-empty-or-nil-p method)
+                      (string-empty-p tramp-postfix-method-format))
             (concat method tramp-postfix-method-format))
-          (unless (zerop (length user))
+          (unless (tramp-string-empty-or-nil-p user)
            (concat user tramp-postfix-user-format))
-         (unless (zerop (length host))
+         (unless (tramp-string-empty-or-nil-p host)
            (concat
             (if (string-match-p tramp-ipv6-regexp host)
                 (concat
@@ -1940,9 +1944,9 @@ of `current-buffer'."
   (let ((method (tramp-file-name-method vec))
        (user-domain (tramp-file-name-user-domain vec))
        (host-port (tramp-file-name-host-port vec)))
-    (if (not (zerop (length user-domain)))
-       (format "*debug tramp/%s %s@%s*" method user-domain host-port)
-      (format "*debug tramp/%s %s*" method host-port))))
+    (if (tramp-string-empty-or-nil-p user-domain)
+       (format "*debug tramp/%s %s*" method host-port)
+      (format "*debug tramp/%s %s@%s*" method user-domain host-port))))
 
 (put #'tramp-debug-buffer-name 'tramp-suppress-trace t)
 
@@ -2942,10 +2946,10 @@ not in completion mode."
         (tramp-drop-volume-letter (expand-file-name filename directory)))
        ;; When `tramp-syntax' is `simplified', we need a default method.
        (tramp-default-method
-        (and (zerop (length tramp-postfix-method-format))
+        (and (string-empty-p tramp-postfix-method-format)
              tramp-default-method))
        (tramp-default-method-alist
-        (and (zerop (length tramp-postfix-method-format))
+        (and (string-empty-p tramp-postfix-method-format)
              tramp-default-method-alist))
        tramp-default-user tramp-default-user-alist
        tramp-default-host tramp-default-host-alist
@@ -3768,7 +3772,7 @@ Let-bind it when necessary.")
   ;; Otherwise, remove any trailing slash from localname component.
   ;; Method, host, etc, are unchanged.
   (while (with-parsed-tramp-file-name directory nil
-          (and (not (zerop (length localname)))
+          (and (tramp-compat-length> localname 0)
                (eq (aref localname (1- (length localname))) ?/)
                (not (string= localname "/"))))
     (setq directory (substring directory 0 -1)))
@@ -3799,7 +3803,8 @@ Let-bind it when necessary.")
   ;; If DIR is not given, use DEFAULT-DIRECTORY or "/".
   (setq dir (or dir default-directory "/"))
   ;; Handle empty NAME.
-  (when (zerop (length name)) (setq name "."))
+  (when (string-empty-p name)
+    (setq name "."))
   ;; Unless NAME is absolute, concat DIR and NAME.
   (unless (file-name-absolute-p name)
     (setq name (tramp-compat-file-name-concat dir name)))
@@ -3818,7 +3823,7 @@ Let-bind it when necessary.")
        (let ((uname (match-string 1 localname))
              (fname (match-string 2 localname))
              hname)
-         (when (zerop (length uname))
+         (when (tramp-string-empty-or-nil-p uname)
            (setq uname user))
          (when (setq hname (tramp-get-home-directory v uname))
            (setq localname (concat hname fname)))))
@@ -3901,7 +3906,7 @@ Let-bind it when necessary.")
     ;; Run the command on the localname portion only unless we are in
     ;; completion mode.
     (tramp-make-tramp-file-name
-     v (or (and (zerop (length (tramp-file-name-localname v)))
+     v (or (and (tramp-string-empty-or-nil-p (tramp-file-name-localname v))
                (not (tramp-connectable-p file)))
           (tramp-run-real-handler
            #'file-name-as-directory
@@ -3964,7 +3969,8 @@ Let-bind it when necessary.")
     ;; "." and ".." are never interesting as completions, and are
     ;; actually in the way in a directory with only one file.  See
     ;; file_name_completion() in dired.c.
-    (when (and (consp fnac) (= (length (delete "./" (delete "../" fnac))) 1))
+    (when (and (consp fnac)
+              (tramp-compat-length= (delete "./" (delete "../" fnac)) 1))
       (setq fnac (delete "./" (delete "../" fnac))))
     (or
      (try-completion
@@ -4725,7 +4731,7 @@ substitution.  SPEC-LIST is a list of char/value pairs 
used for
          (tramp-get-connection-property v "direct-async-process")
         ;; There's no multi-hop.
         (or (not (tramp-multi-hop-p v))
-            (= (length (tramp-compute-multi-hops v)) 1))
+            (null (cdr (tramp-compute-multi-hops v))))
         ;; There's no remote stdout or stderr file.
         (or (not (stringp buffer)) (not (tramp-tramp-file-p buffer)))
         (or (not (stringp stderr)) (not (tramp-tramp-file-p stderr))))))
@@ -6343,7 +6349,7 @@ are written with verbosity of 6."
       (error
        (setq error (error-message-string err)
             result 1)))
-    (if (zerop (length error))
+    (if (tramp-string-empty-or-nil-p error)
        (tramp-message vec 6 "%s\n%s" result output)
       (tramp-message vec 6 "%s\n%s\n%s" result output error))
     result))
@@ -6479,7 +6485,7 @@ Consults the auth-source package."
 
       ;; Workaround.  Prior Emacs 28.1, auth-source has saved empty
       ;; passwords.  See discussion in Bug#50399.
-      (when (zerop (length auth-passwd))
+      (when (tramp-string-empty-or-nil-p auth-passwd)
        (setq tramp-password-save-function nil))
       (tramp-set-connection-property vec "first-password-request" nil)
 
diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el
index 6a733f09db..3b2c4cba62 100644
--- a/lisp/org/org-mouse.el
+++ b/lisp/org/org-mouse.el
@@ -241,7 +241,7 @@ return `:middle'."
    (t :middle)))
 
 (defun org-mouse-empty-line ()
-  "Return non-nil iff the line contains only white space."
+  "Return non-nil if the line contains only white space."
   (save-excursion (beginning-of-line) (looking-at "[ \t]*$")))
 
 (defun org-mouse-next-heading ()
@@ -283,7 +283,7 @@ keyword as the only argument.
 
 If SELECTED is nil, then all items are normal menu items.  If
 SELECTED is a function, then each item is a checkbox, which is
-enabled for a given keyword iff (funcall SELECTED keyword) return
+enabled for a given keyword if (funcall SELECTED keyword) return
 non-nil.  If SELECTED is neither nil nor a function, then the
 items are radio buttons.  A radio button is enabled for the
 keyword `equal' to SELECTED.
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 5bee515246..1ca7a21336 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -632,6 +632,13 @@ This will modify the current buffer."
 ;;; Internal Functions:
 
 ;; argument handling
+(defsubst pcomplete-actual-arg (&optional index offset)
+  "Return the actual text representation of the last argument.
+This is different from `pcomplete-arg', which returns the textual value
+that the last argument evaluated to.  This function returns what the
+user actually typed in."
+  (buffer-substring (pcomplete-begin index offset) (point)))
+
 (defun pcomplete-arg (&optional index offset)
   "Return the textual content of the INDEXth argument.
 INDEX is based from the current processing position.  If INDEX is
@@ -659,11 +666,20 @@ the pcomplete-arg-value text property of that string."
                   (_      (- pcomplete-index (or index 0))))
                 (or offset 0))
               pcomplete-args)))
-    (if (stringp arg)
+    (if (or (stringp arg)
+            ;; FIXME: 'last' is handled specially in Emacs 29, because
+            ;; 'pcomplete-parse-arguments' accepts a list of strings
+            ;; (which are completion candidates) as return value for
+            ;; (pcomplete-arg 'last).  See below: "it means it's a
+            ;; list of completions computed during parsing,
+            ;; e.g. Eshell uses that to turn globs into lists of
+            ;; completions".  This special case will be dealt with
+            ;; differently in Emacs 30: the pcomplete-arg-value
+            ;; property will be used by 'pcomplete-parse-arguments'.
+            (eq index 'last))
         arg
       (propertize
-       (buffer-substring (pcomplete-begin index offset)
-                         (pcomplete-begin (1- (or index 0)) offset))
+       (car (split-string (pcomplete-actual-arg index offset)))
        'pcomplete-arg-value arg))))
 
 (defun pcomplete-begin (&optional index offset)
@@ -679,13 +695,6 @@ See the documentation for `pcomplete-arg'."
       (setq index (+ index offset)))
   (nth index pcomplete-begins))
 
-(defsubst pcomplete-actual-arg (&optional index offset)
-  "Return the actual text representation of the last argument.
-This is different from `pcomplete-arg', which returns the textual value
-that the last argument evaluated to.  This function returns what the
-user actually typed in."
-  (buffer-substring (pcomplete-begin index offset) (point)))
-
 (defsubst pcomplete-next-arg ()
   "Move the various pointers to the next argument."
   (setq pcomplete-index (1+ pcomplete-index)
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index b2151775e9..c066a79815 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -118,7 +118,6 @@ MODE is either `c' or `cpp'."
          `(((parent-is "translation_unit") parent-bol 0)
            ((node-is ")") parent 1)
            ((node-is "]") parent-bol 0)
-           ((node-is "}") c-ts-mode--bracket-children-anchor 0)
            ((node-is "else") parent-bol 0)
            ((node-is "case") parent-bol 0)
            ((node-is "preproc_arg") no-indent)
@@ -130,17 +129,28 @@ MODE is either `c' or `cpp'."
             c-ts-mode--comment-2nd-line-anchor
             1)
            ((parent-is "comment") prev-adaptive-prefix 0)
-           (c-ts-mode--top-level-label-matcher point-min 1)
+
+           ;; Labels.
            ((node-is "labeled_statement") parent-bol 0)
-           ((parent-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
+           ((parent-is "labeled_statement")
+            point-min c-ts-mode--statement-offset)
+
            ((match "preproc_ifdef" "compound_statement") point-min 0)
            ((match "#endif" "preproc_ifdef") point-min 0)
            ((match "preproc_if" "compound_statement") point-min 0)
            ((match "#endif" "preproc_if") point-min 0)
            ((match "preproc_function_def" "compound_statement") point-min 0)
            ((match "preproc_call" "compound_statement") point-min 0)
+
+           ;; {} blocks.
+           ((node-is "}") point-min c-ts-mode--close-bracket-offset)
            ((parent-is "compound_statement")
-            c-ts-mode--bracket-children-anchor c-ts-mode-indent-offset)
+            point-min c-ts-mode--statement-offset)
+           ((parent-is "enumerator_list")
+            point-min c-ts-mode--statement-offset)
+           ((parent-is "field_declaration_list")
+            point-min c-ts-mode--statement-offset)
+
            ((parent-is "function_definition") parent-bol 0)
            ((parent-is "conditional_expression") first-sibling 0)
            ((parent-is "assignment_expression") parent-bol 
c-ts-mode-indent-offset)
@@ -156,12 +166,11 @@ MODE is either `c' or `cpp'."
            ((query "(for_statement update: (_) @indent)") parent-bol 5)
            ((query "(call_expression arguments: (_) @indent)") parent 
c-ts-mode-indent-offset)
            ((parent-is "call_expression") parent 0)
-           ((parent-is "enumerator_list") parent-bol c-ts-mode-indent-offset)
            ,@(when (eq mode 'cpp)
                '(((node-is "access_specifier") parent-bol 0)
                  ;; Indent the body of namespace definitions.
                  ((parent-is "declaration_list") parent-bol 
c-ts-mode-indent-offset)))
-           ((parent-is "field_declaration_list") parent-bol 
c-ts-mode-indent-offset)
+
            ((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset)
            ((parent-is "if_statement") parent-bol c-ts-mode-indent-offset)
            ((parent-is "for_statement") parent-bol c-ts-mode-indent-offset)
@@ -174,6 +183,7 @@ MODE is either `c' or `cpp'."
     `((gnu
        ;; Prepend rules to set highest priority
        ((match "while" "do_statement") parent 0)
+       (c-ts-mode--top-level-label-matcher point-min 1)
        ,@common)
       (k&r ,@common)
       (linux
@@ -210,25 +220,55 @@ NODE should be a labeled_statement."
   (let ((func (treesit-parent-until
                node (lambda (n)
                       (equal (treesit-node-type n)
-                             "function_definition")))))
+                             "compound_statement")))))
     (and (equal (treesit-node-type node)
                 "labeled_statement")
-         (not (treesit-node-top-level func "function_definition")))))
-
-(defun c-ts-mode--bracket-children-anchor (_n parent &rest _)
-  "This anchor is used for children of a compound_statement.
-So anything inside a {} block.  PARENT should be the
-compound_statement.  This anchor looks at the {, if itson its own
-line, anchor at it, if it has stuff before it, anchor at the
-beginning of grandparent."
-  (save-excursion
-    (goto-char (treesit-node-start parent))
-    (let ((bol (line-beginning-position)))
-      (skip-chars-backward " \t")
-      (treesit-node-start
-       (if (< bol (point))
-           (treesit-node-parent parent)
-         parent)))))
+         (not (treesit-node-top-level func "compound_statement")))))
+
+(defvar c-ts-mode-indent-block-type-regexp
+  (rx (or "compound_statement"
+          "field_declaration_list"
+          "enumeratior_list"))
+  "Regexp matching types of block nodes (i.e., {} blocks).")
+
+(defun c-ts-mode--statement-offset (node parent &rest _)
+  "This anchor is used for children of a statement inside a block.
+
+This function basically counts the number of block nodes (defined
+by `c-ts-mode--indent-block-type-regexp') between NODE and the
+root node (not counting NODE itself), and multiply that by
+`c-ts-mode-indent-offset'.
+
+To support GNU style, on each block level, this function also
+checks whether the opening bracket { is on its own line, if so,
+it adds an extra level, except for the top-level.
+
+PARENT is NODE's parent."
+  (let ((level 0))
+    ;; If point is on an empty line, NODE would be nil, but we pretend
+    ;; there is a statement node.
+    (when (null node)
+      (setq node t))
+    (while (if (eq node t)
+               (setq node parent)
+             (setq node (treesit-node-parent node)))
+      (when (string-match-p c-ts-mode-indent-block-type-regexp
+                            (treesit-node-type node))
+        (cl-incf level)
+        (save-excursion
+          (goto-char (treesit-node-start node))
+          (cond ((bolp) nil)
+                ((looking-back (rx bol (* whitespace))
+                               (line-beginning-position))
+                 (cl-incf level))))))
+    (* level c-ts-mode-indent-offset)))
+
+(defun c-ts-mode--close-bracket-offset (node parent &rest _)
+  "Offset for the closing bracket, NODE.
+It's basically one level less that the statements in the block.
+PARENT is NODE's parent."
+  (- (c-ts-mode--statement-offset node parent)
+     c-ts-mode-indent-offset))
 
 (defun c-ts-mode--looking-at-star (_n _p bol &rest _)
   "A tree-sitter simple indent matcher.
@@ -254,14 +294,15 @@ PARENT should be a comment node."
          (back-to-indentation)
          (eq (point) (treesit-node-start parent)))))
 
-(defun c-ts-mode--comment-2nd-line-anchor (&rest _)
+(defun c-ts-mode--comment-2nd-line-anchor (_n _p bol &rest _)
   "Return appropriate anchor for the second line of a comment.
 
 If the first line is /* alone, return the position right after
 the star; if the first line is /* followed by some text, return
 the position right before the text minus 1.
 
-Use an offset of 1 with this anchor."
+Use an offset of 1 with this anchor.  BOL is the beginning of
+non-whitespace characters of the current line."
   (save-excursion
     (forward-line -1)
     (back-to-indentation)
@@ -270,8 +311,17 @@ Use an offset of 1 with this anchor."
       (if (looking-at (rx (* (or " " "\t")) eol))
           ;; Only /* at the first line.
           (progn (skip-chars-backward " \t")
-                 (point))
-        ;; There is something after /* at the first line.
+                 (if (save-excursion
+                       (goto-char bol)
+                       (looking-at (rx "*")))
+                     ;; The common case.  Checked by "Multiline Block
+                     ;; Comments 4".
+                     (point)
+                   ;; The "Multiline Block Comments 2" test in
+                   ;; c-ts-mode-resources/indent.erts checks this.
+                   (1- (point))))
+        ;; There is something after /* at the first line.  The
+        ;; "Multiline Block Comments 3" test checks this.
         (1- (point))))))
 
 ;;; Font-lock
@@ -671,79 +721,94 @@ the semicolon.  This function skips the semicolon."
 
 ;;; Filling
 
+(defvar c-ts-mode--comment-regexp
+  ;; These covers C/C++, Java, JavaScript, TypeScript, Rust, C#.
+  (rx (or "comment" "line_comment" "block_comment"))
+  "Regexp pattern that matches a comment in C-like languages.")
+
 (defun c-ts-mode--fill-paragraph (&optional arg)
   "Fillling function for `c-ts-mode'.
 ARG is passed to `fill-paragraph'."
   (interactive "*P")
   (save-restriction
     (widen)
-    (let* ((node (treesit-node-at (point)))
-           (start (treesit-node-start node))
-           (end (treesit-node-end node))
-           ;; Bind to nil to avoid infinite recursion.
-           (fill-paragraph-function nil)
-           (orig-point (point-marker))
-           (start-marker nil)
-           (end-marker nil)
-           (end-len 0))
-      ;; These covers C/C++, Java, JavaScript, TypeScript, Rust, C#.
-      (when (member (treesit-node-type node)
-                    '("comment" "line_comment" "block_comment"))
-        ;; We mask "/*" and the space before "*/" like
-        ;; `c-fill-paragraph' does.
-        (atomic-change-group
-          ;; Mask "/*".
-          (goto-char start)
-          (when (looking-at (rx (* (syntax whitespace))
-                                (group "/") "*"))
-            (goto-char (match-beginning 1))
-            (setq start-marker (point-marker))
-            (replace-match " " nil nil nil 1))
-          ;; Include whitespaces before /*.
-          (goto-char start)
-          (beginning-of-line)
-          (setq start (point))
-          ;; Mask spaces before "*/" if it is attached at the end
-          ;; of a sentence rather than on its own line.
-          (goto-char end)
-          (when (looking-back (rx (not (syntax whitespace))
-                                  (group (+ (syntax whitespace)))
-                                  "*/")
-                              (line-beginning-position))
-            (goto-char (match-beginning 1))
-            (setq end-marker (point-marker))
-            (setq end-len (- (match-end 1) (match-beginning 1)))
-            (replace-match (make-string end-len ?x)
-                           nil nil nil 1))
-          ;; If "*/" is on its own line, don't included it in the
-          ;; filling region.
-          (when (not end-marker)
-            (goto-char end)
-            (when (looking-back (rx "*/") 2)
-              (backward-char 2)
-              (skip-syntax-backward "-")
-              (setq end (point))))
-          ;; Let `fill-paragraph' do its thing.
-          (goto-char orig-point)
-          (narrow-to-region start end)
-          ;; We don't want to fill the region between START and
-          ;; START-MARKER, otherwise the filling function might delete
-          ;; some spaces there.
-          (fill-region start-marker end arg)
-          ;; Unmask.
-          (when start-marker
-            (goto-char start-marker)
-            (delete-char 1)
-            (insert "/"))
-          (when end-marker
-            (goto-char end-marker)
-            (delete-region (point) (+ end-len (point)))
-            (insert (make-string end-len ?\s))))
-        (goto-char orig-point))
+    (let ((node (treesit-node-at (point))))
+      (when (string-match-p c-ts-mode--comment-regexp
+                            (treesit-node-type node))
+        (if (save-excursion
+              (goto-char (treesit-node-start node))
+              (looking-at "//"))
+            (fill-comment-paragraph arg)
+          (c-ts-mode--fill-block-comment arg)))
       ;; Return t so `fill-paragraph' doesn't attempt to fill by
       ;; itself.
       t)))
 
+(defun c-ts-mode--fill-block-comment (&optional arg)
+  "Fillling function for block comments.
+ARG is passed to `fill-paragraph'.  Assume point is in a block
+comment."
+  (let* ((node (treesit-node-at (point)))
+         (start (treesit-node-start node))
+         (end (treesit-node-end node))
+         ;; Bind to nil to avoid infinite recursion.
+         (fill-paragraph-function nil)
+         (orig-point (point-marker))
+         (start-marker (point-marker))
+         (end-marker nil)
+         (end-len 0))
+    (move-marker start-marker start)
+    ;; We mask "/*" and the space before "*/" like
+    ;; `c-fill-paragraph' does.
+    (atomic-change-group
+      ;; Mask "/*".
+      (goto-char start)
+      (when (looking-at (rx (* (syntax whitespace))
+                            (group "/") "*"))
+        (goto-char (match-beginning 1))
+        (move-marker start-marker (point))
+        (replace-match " " nil nil nil 1))
+      ;; Include whitespaces before /*.
+      (goto-char start)
+      (beginning-of-line)
+      (setq start (point))
+      ;; Mask spaces before "*/" if it is attached at the end
+      ;; of a sentence rather than on its own line.
+      (goto-char end)
+      (when (looking-back (rx (not (syntax whitespace))
+                              (group (+ (syntax whitespace)))
+                              "*/")
+                          (line-beginning-position))
+        (goto-char (match-beginning 1))
+        (setq end-marker (point-marker))
+        (setq end-len (- (match-end 1) (match-beginning 1)))
+        (replace-match (make-string end-len ?x)
+                       nil nil nil 1))
+      ;; If "*/" is on its own line, don't included it in the
+      ;; filling region.
+      (when (not end-marker)
+        (goto-char end)
+        (when (looking-back (rx "*/") 2)
+          (backward-char 2)
+          (skip-syntax-backward "-")
+          (setq end (point))))
+      ;; Let `fill-paragraph' do its thing.
+      (goto-char orig-point)
+      (narrow-to-region start end)
+      ;; We don't want to fill the region between START and
+      ;; START-MARKER, otherwise the filling function might delete
+      ;; some spaces there.
+      (fill-region start-marker end arg)
+      ;; Unmask.
+      (when start-marker
+        (goto-char start-marker)
+        (delete-char 1)
+        (insert "/"))
+      (when end-marker
+        (goto-char end-marker)
+        (delete-region (point) (+ end-len (point)))
+        (insert (make-string end-len ?\s))))))
+
 (defun c-ts-mode-comment-setup ()
   "Set up local variables for C-like comment.
 
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 30893638f0..4405ce0fe0 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -113,6 +113,7 @@
 ;; Various floating point types and operations are also supported but the
 ;; actual precision is limited by the Emacs internal floating representation,
 ;; which is the C data type "double" or IEEE binary64 format.
+;; C99 and GNU style variadic arguments support is completed in 2022/E.
 
 ;;; Code:
 
@@ -392,8 +393,10 @@ If there is a marked region from START to END it only 
shows the symbols within."
 (add-hook 'after-revert-hook 'hif-after-revert-function)
 
 (defun hif-end-of-line ()
+  "Find the end-point of line concatenation."
   (end-of-line)
-  (while (= (logand 1 (skip-chars-backward "\\\\")) 1)
+  (while (progn (skip-chars-backward " \t" (line-beginning-position))
+                (= ?\\ (char-before)))
     (end-of-line 2)))
 
 (defun hif-merge-ifdef-region (start end)
@@ -536,10 +539,10 @@ that form should be displayed.")
 ;;===%%SF%% parsing (Start)  ===
 ;;;  The code that understands what ifs and ifdef in files look like.
 
-(defconst hif-cpp-prefix      "\\(^\\|\r\\)[ \t]*#[ \t]*")
+(defconst hif-cpp-prefix      "\\(^\\|\r\\)?[ \t]*#[ \t]*")
 (defconst hif-ifxdef-regexp   (concat hif-cpp-prefix "if\\(n\\)?def"))
 (defconst hif-ifndef-regexp   (concat hif-cpp-prefix "ifndef"))
-(defconst hif-ifx-regexp      (concat hif-cpp-prefix "if\\(n?def\\)?[ \t]+"))
+(defconst hif-ifx-regexp      (concat hif-cpp-prefix "if\\((\\|\\(n?def\\)?[ 
\t]+\\)"))
 (defconst hif-elif-regexp     (concat hif-cpp-prefix "elif"))
 (defconst hif-else-regexp     (concat hif-cpp-prefix "else"))
 (defconst hif-endif-regexp    (concat hif-cpp-prefix "endif"))
@@ -547,18 +550,23 @@ that form should be displayed.")
   (concat hif-ifx-regexp "\\|" hif-elif-regexp "\\|" hif-else-regexp "\\|"
           hif-endif-regexp))
 (defconst hif-macro-expr-prefix-regexp
-  (concat hif-cpp-prefix "\\(if\\(n?def\\)?\\|elif\\|define\\)[ \t]+"))
+  (concat hif-cpp-prefix "\\(if(\\|if\\(n?def\\)?[ \t]+\\|elif\\|define[ 
\t]+\\)"))
 
-(defconst hif-white-regexp    "[ \t]*")
+(defconst hif-line-concat     "\\\\[ \t]*[\n\r]")
+;; If `hif-white-regexp' is modified, `hif-tokenize' might need to be modified
+;; accordingly.
+(defconst hif-white-regexp    (concat "\\(?:\\(?:[ \t]\\|/\\*.*\\*/\\)*"
+                                      "\\(?:" hif-line-concat "\\)?\\)*"))
 (defconst hif-define-regexp   (concat hif-cpp-prefix "\\(define\\|undef\\)"))
 (defconst hif-id-regexp       (concat "[[:alpha:]_][[:alnum:]_]*"))
+(defconst hif-etc-regexp      "\\.\\.\\.")
 (defconst hif-macroref-regexp
   (concat hif-white-regexp "\\(" hif-id-regexp "\\)"
           "\\("
           "(" hif-white-regexp
           "\\(" hif-id-regexp "\\)?" hif-white-regexp
           "\\(" "," hif-white-regexp hif-id-regexp hif-white-regexp "\\)*"
-          "\\(\\.\\.\\.\\)?" hif-white-regexp
+          "\\(" "," hif-white-regexp "\\)?" "\\(" hif-etc-regexp "\\)?" 
hif-white-regexp
           ")"
           "\\)?" ))
 
@@ -936,7 +944,11 @@ Assuming we've just performed a `hif-token-regexp' lookup."
 (defun hif-tokenize (start end)
   "Separate string between START and END into a list of tokens."
   (let ((token-list nil)
-        (white-regexp "[ \t]+")
+        ;; Similar to `hif-white-regexp' but keep the spaces if there are
+        (white-regexp (concat "\\(?:"
+                              "\\(?:\\([ \t]+\\)\\|\\(?:/\\*.*\\*/\\)?\\)*"
+                              "\\(?:" hif-line-concat "\\)?"
+                              "\\)*"))
         token)
     (setq hif-simple-token-only t)
     (with-syntax-table hide-ifdef-syntax-table
@@ -956,29 +968,31 @@ Assuming we've just performed a `hif-token-regexp' 
lookup."
               (forward-char 2))
 
              ((looking-at hif-string-literal-regexp)
-              (setq token (substring-no-properties (match-string 1)))
+              (setq token (match-string-no-properties 1))
               (goto-char (match-end 0))
               (when (looking-at white-regexp)
-                (add-text-properties 0 1 '(hif-space t) token)
+                (if (not (zerop (length (match-string-no-properties 1))))
+                    (add-text-properties 0 1 '(hif-space t) token))
                 (goto-char (match-end 0)))
               (push token token-list))
 
              ((looking-at hif-token-regexp)
               (goto-char (match-end 0))
-              (setq token (hif-strtok
-                           (substring-no-properties (match-string 0))))
+              (setq token (hif-strtok (match-string-no-properties 0)))
               (push token token-list)
               (when (looking-at white-regexp)
-                ;; We can't just append a space to the token string, otherwise
-                ;; `0xf0 ' ## `01' will become `0xf0 01' instead of the 
expected
-                ;; `0xf001', hence a standalone `hif-space' is placed instead.
-                (push 'hif-space token-list)
+                (if (not (zerop (length (match-string-no-properties 1))))
+                    ;; We can't just append a space to the token string,
+                    ;; otherwise `0xf0 ' ## `01' will become `0xf0 01' instead
+                    ;; of the expected `0xf001', hence a standalone `hif-space'
+                    ;; is placed instead.
+                    (push 'hif-space token-list))
                 (goto-char (match-end 0))))
 
              ((looking-at "\r") ; Sometimes MS-Windows user will leave CR in
               (forward-char 1)) ;  the source code. Let's not get stuck here.
 
-             (t (error "Bad #if expression: %s" (buffer-string)))))))
+             (t (error "Bad preprocessor expression: %s" (buffer-string)))))))
       (if (eq 'hif-space (car token-list))
           (setq token-list (cdr token-list))) ;; remove trailing white space
       (nreverse token-list))))
@@ -1126,7 +1140,7 @@ this is to emulate the stringification behavior of C++ 
preprocessor."
                                 (and (eq (car remains) 'hif-space)
                                      (eq (cadr remains) 'hif-lparen)
                                      (setq remains (cdr remains)))))
-                       ;; No argument, no invocation
+                       ;; No argument list, no invocation
                        tok
                      ;; Argumented macro, get arguments and invoke it.
                      ;; Dynamically bind `hif-token-list' and `hif-token'
@@ -1369,8 +1383,9 @@ factor : `!' factor | `~' factor | `(' exprlist `)' | 
`defined(' id `)' |
         (parmlist nil) ; A "token" list of parameters, will later be parsed
         (parm nil))
 
-    (while (or (not (eq (hif-nexttoken keep-space) 'hif-rparen))
-               (/= nest 0))
+    (while (and (or (not (eq (hif-nexttoken keep-space) 'hif-rparen))
+                    (/= nest 0))
+                hif-token)
       (if (eq (car (last parm)) 'hif-comma)
           (setq parm nil))
       (cond
@@ -1384,6 +1399,8 @@ factor : `!' factor | `~' factor | `(' exprlist `)' | 
`defined(' id `)' |
         (setq parm nil)))
       (push hif-token parm))
 
+    (if (equal parm '(hif-comma)) ;; missing the last argument
+        (setq parm '(nil)))
     (push (nreverse parm) parmlist) ; Okay even if PARM is nil
     (hif-nexttoken keep-space) ; Drop the `hif-rparen', get next token
     (nreverse parmlist)))
@@ -1609,11 +1626,21 @@ and `+='...)."
     ;; no need to reassemble the list if no `##' presents
     l))
 
-(defun hif-delimit (lis atom)
-  (nconc (mapcan (lambda (l) (list l atom))
+(defun hif-delimit (lis elem)
+  (nconc (mapcan (lambda (l) (list l elem))
                  (butlast lis))
          (last lis)))
 
+(defun hif-delete-nth (n lst)
+  "Non-destructively delete the nth item from a list."
+  (if (zerop n)
+      (cdr lst)
+    ;; non-destructive
+    (let* ((duplst (copy-sequence lst))
+           (node (nthcdr (1- n) duplst)))
+      (setcdr node (cddr node))
+      duplst)))
+
 ;; Perform token replacement:
 (defun hif-macro-supply-arguments (macro-name actual-parms)
   "Expand a macro call, replace ACTUAL-PARMS in the macro body."
@@ -1633,49 +1660,160 @@ and `+='...)."
       ;; For each actual parameter, evaluate each one and associate it
       ;; with an actual parameter, put it into local table and finally
       ;; evaluate the macro body.
-      (if (setq etc (eq (car formal-parms) 'hif-etc))
+      (if (setq etc (or (eq (car formal-parms) 'hif-etc)
+                        (and (eq (car formal-parms) 'hif-etc-c99) 'c99)))
           ;; Take care of `hif-etc' first. Prefix `hif-comma' back if needed.
           (setq formal-parms (cdr formal-parms)))
       (setq formal-count (length formal-parms)
             actual-count (length actual-parms))
 
-      (if (> formal-count actual-count)
-          (error "Too few parameters for macro %S" macro-name)
-        (if (< formal-count actual-count)
-            (or etc
-                (error "Too many parameters for macro %S" macro-name))))
+      ;; Fix empty arguments applied
+      (if (and (= formal-count 1)
+               (null (car formal-parms)))
+          (setq formal-parms nil
+                formal-count (1- formal-count)))
+      (if (and (= actual-count 1)
+               (or (null (car actual-parms))
+                   ;; white space as the only argument
+                   (equal '(hif-space) (car actual-parms))))
+          (setq actual-parms nil
+                actual-count (1- actual-count)))
+
+      ;; Basic error checking
+      (if etc
+          (if (eq etc 'c99)
+              (if (and (> formal-count 1) ; f(a,b,...)
+                       (< actual-count formal-count))
+                  (error "C99 variadic argument macro %S need at least %d 
arguments"
+                         macro-name formal-count))
+            ;; GNU style variadic argument
+            (if (and (> formal-count 1)
+                     (< actual-count (1- formal-count)))
+                (error "GNU variadic argument macro %S need at least %d 
arguments"
+                       macro-name (1- formal-count))))
+        (if (> formal-count actual-count)
+            (error "Too few parameters for macro %S; %d instead of %d"
+                   macro-name actual-count formal-count)
+          (if (< formal-count actual-count)
+              (error "Too many parameters for macro %S; %d instead of %d"
+                     macro-name actual-count formal-count))))
 
       ;; Perform token replacement on the MACRO-BODY with the parameters
-      (while (setq formal (pop formal-parms))
-        ;; Prevent repetitive substitution, thus cannot use `subst'
-        ;; for example:
-        ;; #define mac(a,b) (a+b)
-        ;; #define testmac mac(b,y)
-        ;; testmac should expand to (b+y): replace of argument a and b
-        ;; occurs simultaneously, not sequentially. If sequentially,
-        ;; according to the argument order, it will become:
-        ;; 1. formal parm #1 'a' replaced by actual parm 'b', thus (a+b)
-        ;;    becomes (b+b)
-        ;; 2. formal parm #2 'b' replaced by actual parm 'y', thus (b+b)
-        ;;    becomes (y+y).
-        (setq macro-body
-              ;; Unlike `subst', `substitute' replace only the top level
-              ;; instead of the whole tree; more importantly, it's not
-              ;; destructive.
-              (cl-substitute (if (and etc (null formal-parms))
-                                 (hif-delimit actual-parms 'hif-comma)
-                               (car actual-parms))
-                             formal macro-body))
-        (setq actual-parms (cdr actual-parms)))
-
-        ;; Replacement completed, stringifiy and concatenate the token list.
-        ;; Stringification happens must take place before flattening, otherwise
-        ;; only the first token will be stringified.
-        (setq macro-body
-              (flatten-tree (hif-token-stringification macro-body)))
-
-        ;; Token concatenation happens here, keep single 'hif-space
-        (hif-keep-single (hif-token-concatenation macro-body) 'hif-space))))
+
+      ;; Every substituted argument in the macro-body must be in list form so
+      ;; that it won't again be substituted incorrectly in later iterations.
+      ;; Finally we will flatten the list to fix that.
+      (cl-loop
+       do
+       ;; Note that C99 '...' and GNU 'x...' allow empty match
+       (setq formal (pop formal-parms))
+       ;;
+       ;; Prevent repetitive substitution, thus cannot use `subst'
+       ;; for example:
+       ;;   #define mac(a,b) (a+b)
+       ;;   #define testmac mac(b,y)
+       ;;   testmac should expand to (b+y): replace of argument a and b
+       ;;   occurs simultaneously, not sequentially. If sequentially,
+       ;;   according to the argument order, it will become:
+       ;;   1. formal parm #1 'a' replaced by actual parm 'b', thus (a+b)
+       ;;      becomes (b+b)
+       ;;   2. formal parm #2 'b' replaced by actual parm 'y', thus (b+b)
+       ;;      becomes (y+y).
+       ;; Unlike `subst', `cl-substitute' replace only the top level
+       ;; instead of the whole tree; more importantly, it's not
+       ;; destructive.
+       ;;
+       (if (not (and (null formal-parms) etc))
+           ;; One formal with one actual
+           (setq macro-body
+                 (cl-substitute (car actual-parms) formal macro-body))
+         ;; `formal-parms' used up, now take care of '...'
+         (cond
+
+          ((eq etc 'c99) ; C99 __VA_ARGS__ style '...'
+           (when formal
+             (setq macro-body
+                   (cl-substitute (car actual-parms) formal macro-body))
+             ;; Now the whole __VA_ARGS__ represents the whole
+             ;; remaining actual params
+             (pop actual-parms))
+           ;; Replace if __VA_ARGS__ presents:
+           ;;   if yes, see if it's prefixed with ", ##" or not,
+           ;;    if yes, remove the "##", then if actual-params is
+           ;;   exhausted, remove the prefixed ',' as well.
+           ;; Prepare for destructive operation
+           (let ((rem-body (copy-sequence macro-body))
+                 new-body va left part)
+             ;; Find each __VA_ARGS__ and remove its immediate prefixed '##'
+             ;; and comma if presents and if `formal_param' is exhausted
+             (while (setq va (cl-position '__VA_ARGS__ rem-body))
+               ;; Split REM-BODY @ __VA_ARGS__ into LEFT and right
+               (setq part nil)
+               (if (zerop va)
+                   (setq left nil ; __VA_ARGS__ trimed
+                         rem-body (cdr rem-body))
+                 (setq left rem-body
+                       rem-body (cdr (nthcdr va rem-body))) ; _V_ removed
+                 (setcdr (nthcdr va left) nil) ; now _V_ be the last in LEFT
+                 ;; now LEFT=(, w? ## w? _V_) rem=(W X Y) where w = white space
+                 (setq left (cdr (nreverse left)))) ; left=(w? ## w? ,)
+
+               ;; Try to recognize w?##w? and remove ", ##" if found
+               ;;   (remember head = __VA_ARGS__ is temporarily removed)
+               (while (and left (eq 'hif-space (car left))) ; skip whites
+                 (setq part (cons 'hif-space part)
+                       left (cdr left)))
+
+               (if (eq (car left) 'hif-token-concat) ; match '##'
+                   (if actual-parms
+                       ;; Keep everything
+                       (setq part (append part (cdr left)))
+                     ;; `actual-params' exhausted, delete ',' if presents
+                     (while (and left (eq 'hif-space (car left))) ; skip whites
+                       (setq part (cons 'hif-space part)
+                             left (cdr left)))
+                     (setq part
+                           (append part
+                                   (if (eq (car left) 'hif-comma) ; match ','
+                                       (cdr left)
+                                     left))))
+                 ;; No immediate '##' found
+                 (setq part (append part left)))
+
+               ;; Insert __VA_ARGS__ as a list
+               (push (hif-delimit actual-parms 'hif-comma) part)
+               ;; Reverse `left' back
+               (setq left (nreverse part)
+                     new-body (append new-body left)))
+
+             ;; Replacement of __VA_ARGS__ done here, add rem-body back
+             (setq macro-body (append new-body rem-body)
+                   actual-parms nil)))
+
+          (etc ; GNU style '...', substitute last argument
+           (if (null actual-parms)
+               ;; Must be non-destructive otherwise the original function
+               ;; definition defined in `hide-ifdef-env' will be destroyed.
+               (setq macro-body (remove formal macro-body))
+             (setq macro-body
+                   (cl-substitute (hif-delimit actual-parms 'hif-comma)
+                                  formal macro-body)
+                   actual-parms nil)))
+
+          (t
+           (error "Interal error: impossible case."))))
+
+       (pop actual-parms)
+       while actual-parms) ; end cl-loop
+
+      ;; Replacement completed, stringifiy and concatenate the token list.
+      ;; Stringification happens must take place before flattening, otherwise
+      ;; only the first token will be stringified.
+      (setq macro-body
+            (flatten-tree (hif-token-stringification macro-body))))
+
+    ;; Token concatenation happens here, keep single 'hif-space
+    (hif-keep-single (hif-token-concatenation macro-body) 'hif-space)))
 
 (defun hif-invoke (macro-name actual-parms)
   "Invoke a macro by expanding it, reparse macro-body and finally invoke it."
@@ -1710,7 +1848,9 @@ and `+='...)."
 Do this when cursor is at the beginning of `regexp' (i.e. #ifX)."
   (let ((case-fold-search nil))
     (save-excursion
-      (re-search-forward regexp)
+      (if (re-search-forward regexp)
+          (if (= ?\( (char-before)) ;; "#if(" found
+              (goto-char (1- (point)))))
       (let* ((curr-regexp (match-string 0))
              (defined (string-match hif-ifxdef-regexp curr-regexp))
              (negate (and defined
@@ -1724,29 +1864,48 @@ Do this when cursor is at the beginning of `regexp' 
(i.e. #ifX)."
             (setq tokens (list 'hif-not tokens)))
         (hif-parse-exp tokens)))))
 
+(defun hif-is-in-comment ()
+  "Check if we're currently within a C(++) comment."
+  (or (nth 4 (syntax-ppss))
+      (looking-at "/[/*]")))
+
+(defun hif-search-ifX-regexp (hif-regexp &optional backward)
+  "Search for a valid ifX regexp defined in hideif."
+  (let ((start (point))
+        (re-search-func (if backward
+                            #'re-search-backward
+                          #'re-search-forward))
+        (limit (if backward (point-min) (point-max)))
+        found)
+    (while (and (setq found
+                      (funcall re-search-func hif-regexp limit t))
+                (hif-is-in-comment)))
+    ;; Jump to the pattern if found
+    (if found
+        (unless backward
+          (setq found
+                (goto-char (- (point) (length (match-string 0))))))
+      (goto-char start))
+    found))
+
 (defun hif-find-any-ifX ()
   "Move to next #if..., or #ifndef, at point or after."
   ;; (message "find ifX at %d" (point))
-  (prog1
-      (re-search-forward hif-ifx-regexp (point-max) t)
-    (beginning-of-line)))
-
+  (hif-search-ifX-regexp hif-ifx-regexp))
 
 (defun hif-find-next-relevant ()
   "Move to next #if..., #elif..., #else, or #endif, after the current line."
   ;; (message "hif-find-next-relevant at %d" (point))
   (end-of-line)
-  ;; Avoid infinite recursion by only going to line-beginning if match found
-  (if (re-search-forward hif-ifx-else-endif-regexp (point-max) t)
-      (beginning-of-line)))
+  ;; Avoid infinite recursion by going to the pattern only if a match is found
+  (hif-search-ifX-regexp hif-ifx-else-endif-regexp))
 
 (defun hif-find-previous-relevant ()
   "Move to previous #if..., #else, or #endif, before the current line."
   ;; (message "hif-find-previous-relevant at %d" (point))
   (beginning-of-line)
-  ;; Avoid infinite recursion by only going to line-beginning if match found
-  (if (re-search-backward hif-ifx-else-endif-regexp (point-min) t)
-     (beginning-of-line)))
+  ;; Avoid infinite recursion by going to the pattern only if a match is found
+  (hif-search-ifX-regexp hif-ifx-else-endif-regexp 't))
 
 
 (defun hif-looking-at-ifX ()
@@ -1931,6 +2090,7 @@ Point is left unchanged."
               ((hif-looking-at-else)
                (setq else (point)))
               (t
+               (beginning-of-line)  ; otherwise #endif line will be hidden
                (setq end (point)))))
       ;; If found #else, look for #endif.
       (when else
@@ -1940,6 +2100,7 @@ Point is left unchanged."
           (hif-ifdef-to-endif))
         (if (hif-looking-at-else)
             (error "Found two elses in a row?  Broken!"))
+        (beginning-of-line) ; otherwise #endif line will be hidden
         (setq end (point)))            ; (line-end-position)
       (hif-make-range start end else elif))))
 
@@ -2085,16 +2246,20 @@ Refer to `hide-ifdef-expand-reinclusion-guard' for more 
details."
            (eq (car def) 'hif-define-macro))
       (let ((cdef (concat "#define " name))
             (parmlist (cadr def))
-            s)
+            p s etc)
         (setq def (caddr def))
         ;; parmlist
         (when parmlist
           (setq cdef (concat cdef "("))
-          (while (car parmlist)
-            (setq cdef (concat cdef (symbol-name (car parmlist))
-                               (if (cdr parmlist) ","))
+          (if (setq etc (or (eq (setq p (car parmlist)) 'hif-etc)
+                            (and (eq p 'hif-etc-c99) 'c99)))
+              (pop parmlist))
+          (while (setq p (car parmlist))
+            (setq cdef (concat cdef (symbol-name p) (if (cdr parmlist) ","))
                   parmlist (cdr parmlist)))
-          (setq cdef (concat cdef ")")))
+          (setq cdef (concat cdef
+                             (if etc (concat (if (eq etc 'c99) ",") "..."))
+                             ")")))
         (setq cdef (concat cdef " "))
         ;; body
         (while def
@@ -2221,25 +2386,38 @@ however, when this command is prefixed, it will display 
the error instead."
         result))))
 
 (defun hif-parse-macro-arglist (str)
-  "Parse argument list formatted as `( arg1 [ , argn] [...] )'.
+  "Parse argument list formatted as `( arg1 [ , argn] [,] [...] )'.
 The `...' is also included.  Return a list of the arguments, if `...' exists 
the
 first arg will be `hif-etc'."
   (let* ((hif-simple-token-only nil) ; Dynamic binding var for `hif-tokenize'
          (tokenlist
           (cdr (hif-tokenize
                 (- (point) (length str)) (point)))) ; Remove `hif-lparen'
-         etc result token)
-    (while (not (eq (setq token (pop tokenlist)) 'hif-rparen))
+         etc result token prevtok prev2tok)
+    (while (not (eq (setq prev2tok prevtok
+                          prevtok token
+                          token (pop tokenlist)) 'hif-rparen))
       (cond
        ((eq token 'hif-etc)
-        (setq etc t))
+        ;; GNU type "..." or C99 type
+        (setq etc (if (or (null prevtok)
+                          (eq prevtok 'hif-comma)
+                          (and (eq prevtok 'hif-space)
+                               (eq prev2tok 'hif-comma)))
+                      'c99 t)))
        ((eq token 'hif-comma)
-        t)
+        (if etc
+            (error "Syntax error: no comma allowed after `...'.")))
        (t
         (push token result))))
-    (if etc
-        (cons 'hif-etc (nreverse result))
-      (nreverse result))))
+    (setq result (nreverse result))
+    (cond
+     ((eq etc 'c99)
+      (cons 'hif-etc-c99 result))
+     ((eq etc t)
+      (cons 'hif-etc result))
+     (t
+      result))))
 
 ;; The original version of hideif evaluates the macro early and store the
 ;; final values for the defined macro into the symbol database (aka
@@ -2280,9 +2458,11 @@ first arg will be `hif-etc'."
         (let* ((defining (string= "define" (match-string 2)))
                (name (and (re-search-forward hif-macroref-regexp max t)
                           (match-string 1)))
-               (parmlist (or (and (match-string 3) ; First arg id found
+               (parmlist (or (and (or (match-string 3) ; First arg id found
+                                      (match-string 6)) ; '...' found
                                   (delq 'hif-space
-                                   (hif-parse-macro-arglist (match-string 2))))
+                                        (hif-parse-macro-arglist
+                                         (match-string 2))))
                              (and (match-string 2) ; empty arglist
                                   (list nil)))))
           (if defining
@@ -2325,7 +2505,8 @@ first arg will be `hif-etc'."
                          (expr (and tokens
                                     ;; `hif-simple-token-only' is checked only
                                     ;; here.
-                                    (or (and hif-simple-token-only
+                                    (or (and (null parmlist)
+                                             hif-simple-token-only
                                              (listp tokens)
                                              (= (length tokens) 1)
                                              (hif-parse-exp tokens))
@@ -2354,13 +2535,22 @@ first arg will be `hif-etc'."
   (save-excursion
     (save-restriction
       ;; (mark-region min max) ;; for debugging
+      (and min (goto-char min))
       (setq hif-verbose-define-count 0)
       (forward-comment (point-max))
-      (while (hif-find-define min max)
-        (forward-comment (point-max))
-        (setf min (point)))
+      (setq min (point))
+      (let ((breakloop nil))
+        (while (and (not breakloop)
+                    (hif-find-define min max))
+          (forward-comment (point-max))
+          (if (and max
+                   (> (point) max))
+              (setq max (point)
+                    breakloop t))
+          (setq min (point))))
       (if max (goto-char max)
-        (goto-char (point-max))))))
+        (goto-char (point-max))
+        nil))))
 
 (defun hide-ifdef-guts ()
   "Does most of the work of `hide-ifdefs'.
@@ -2376,7 +2566,7 @@ It does not do the work that's pointless to redo on a 
recursive entry."
            min max)
       (setq hif-__COUNTER__ 0)
       (goto-char (point-min))
-      (setf min (point))
+      (setq min (point))
       ;; Without this `condition-case' it would be easier to see which
       ;; operation went wrong thru the backtrace `iff' user realize
       ;; the underlying meaning of all hif-* operation; for example,
@@ -2384,11 +2574,11 @@ It does not do the work that's pointless to redo on a 
recursive entry."
       ;; operation arguments would be invalid.
       (condition-case err
           (cl-loop do
-                   (setf max (hif-find-any-ifX))
-                   (hif-add-new-defines min max)
+                   (setq max (hif-find-any-ifX))
+                   (setq max (hif-add-new-defines min max))
                    (if max
                        (hif-possibly-hide expand-header))
-                   (setf min (point))
+                   (setq min (point))
                    while max)
         (error (error "Error: failed at line %d %S"
                       (line-number-at-pos) err))))))
diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el
index eac052ca4f..83c437d307 100644
--- a/lisp/progmodes/java-ts-mode.el
+++ b/lisp/progmodes/java-ts-mode.el
@@ -316,7 +316,8 @@ Return nil if there is no name or if NODE is not a defun 
node."
                             "enum_declaration"
                             "import_declaration"
                             "package_declaration"
-                            "module_declaration")))
+                            "module_declaration"
+                            "constructor_declaration")))
   (setq-local treesit-defun-name-function #'java-ts-mode--defun-name)
 
   (setq-local treesit-sentence-type-regexp
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 902d4fa7ab..fa3b4687ef 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3789,6 +3789,31 @@ Currently there are `js-mode' and `js-ts-mode'."
   ;;(syntax-propertize (point-max))
   )
 
+(defvar js--treesit-sentence-nodes
+  '("import_statement"
+    "debugger_statement"
+    "expression_statement"
+    "if_statement"
+    "switch_statement"
+    "for_statement"
+    "for_in_statement"
+    "while_statement"
+    "do_statement"
+    "try_statement"
+    "with_statement"
+    "break_statement"
+    "continue_statement"
+    "return_statement"
+    "throw_statement"
+    "empty_statement"
+    "labeled_statement"
+    "variable_declaration"
+    "lexical_declaration"
+    "jsx_element"
+    "jsx_self_closing_element")
+  "Nodes that designate sentences in JavaScript.
+See `treesit-sentence-type-regexp' for more information.")
+
 ;;;###autoload
 (define-derived-mode js-ts-mode js-base-mode "JavaScript"
   "Major mode for editing JavaScript.
@@ -3828,6 +3853,10 @@ Currently there are `js-mode' and `js-ts-mode'."
                         "function_declaration"
                         "lexical_declaration")))
     (setq-local treesit-defun-name-function #'js--treesit-defun-name)
+
+    (setq-local treesit-sentence-type-regexp
+                (regexp-opt js--treesit-sentence-nodes))
+
     ;; Fontification.
     (setq-local treesit-font-lock-settings js--treesit-font-lock-settings)
     (setq-local treesit-font-lock-feature-list
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 0786150d90..cd631d048e 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -312,6 +312,30 @@ Argument LANGUAGE is either `typescript' or `tsx'."
    :override t
    '((escape_sequence) @font-lock-escape-face)))
 
+(defvar typescript-ts-mode--sentence-nodes
+  '("import_statement"
+    "debugger_statement"
+    "expression_statement"
+    "if_statement"
+    "switch_statement"
+    "for_statement"
+    "for_in_statement"
+    "while_statement"
+    "do_statement"
+    "try_statement"
+    "with_statement"
+    "break_statement"
+    "continue_statement"
+    "return_statement"
+    "throw_statement"
+    "empty_statement"
+    "labeled_statement"
+    "variable_declaration"
+    "lexical_declaration"
+    "property_signature")
+  "Nodes that designate sentences in TypeScript.
+See `treesit-sentence-type-regexp' for more information.")
+
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode))
 
@@ -344,6 +368,9 @@ Argument LANGUAGE is either `typescript' or `tsx'."
                             "lexical_declaration")))
   (setq-local treesit-defun-name-function #'js--treesit-defun-name)
 
+  (setq-local treesit-sentence-type-regexp
+              (regexp-opt typescript-ts-mode--sentence-nodes))
+
   ;; Imenu (same as in `js-ts-mode').
   (setq-local treesit-simple-imenu-settings
               `(("Function" "\\`function_declaration\\'" nil nil)
@@ -402,6 +429,13 @@ Argument LANGUAGE is either `typescript' or `tsx'."
     (setq-local treesit-simple-indent-rules
                 (typescript-ts-mode--indent-rules 'tsx))
 
+    ;; Navigation
+    (setq-local treesit-sentence-type-regexp
+                (regexp-opt (append
+                             typescript-ts-mode--sentence-nodes
+                             '("jsx_element"
+                               "jsx_self_closing_element"))))
+
     ;; Font-lock.
     (setq-local treesit-font-lock-settings
                 (typescript-ts-mode--font-lock-settings 'tsx))
diff --git a/lisp/simple.el b/lisp/simple.el
index bbcb32cb04..4b09f41de5 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2228,8 +2228,8 @@ are available:
          This includes commands marked as specific to the current
          buffer's modes and commands that have keybindings in the
          current buffer's active local keymaps.  It also includes
-         several commands, like Cuztomize commands, which should
-         always be avaliable."
+         several commands, like Customize commands, which should
+         always be available."
   :version "28.1"
   :group 'completion
   :type '(choice (const :tag "Don't exclude any commands" nil)
@@ -9741,7 +9741,11 @@ the completions is popped up and down."
   "Move to the first item in the completion list."
   (interactive)
   (goto-char (point-min))
-  (unless (get-text-property (point) 'mouse-face)
+  (if (get-text-property (point) 'mouse-face)
+      (unless (get-text-property (point) 'first-completion)
+        (let ((inhibit-read-only t))
+          (add-text-properties (point) (min (1+ (point)) (point-max))
+                               '(first-completion t))))
     (when-let ((pos (next-single-property-change (point) 'mouse-face)))
       (goto-char pos))))
 
diff --git a/lisp/sqlite-mode.el b/lisp/sqlite-mode.el
index 83762b6194..c3047c786f 100644
--- a/lisp/sqlite-mode.el
+++ b/lisp/sqlite-mode.el
@@ -55,10 +55,14 @@
   (interactive "fSQLite file name: ")
   (unless (sqlite-available-p)
     (error "This Emacs doesn't have SQLite support, so it can't view SQLite 
files"))
+  (if (file-remote-p file)
+      (error "Remote SQLite files are not yet supported"))
   (pop-to-buffer (get-buffer-create
                   (format "*SQLite %s*" (file-name-nondirectory file))))
   (sqlite-mode)
   (setq-local sqlite--db (sqlite-open file))
+  (unless (sqlitep sqlite--db)
+    (error "`sqlite-open' failed to open SQLite file"))
   (sqlite-mode-list-tables))
 
 (defun sqlite-mode-list-tables ()
diff --git a/lisp/treesit.el b/lisp/treesit.el
index f2e1b4ac80..e9f5a8b37b 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1511,10 +1511,15 @@ OFFSET."
                return
                (let ((anchor-pos
                       (treesit--simple-indent-eval
-                       (list anchor node parent bol))))
-                 (cons anchor-pos (if (symbolp offset)
-                                      (symbol-value offset)
-                                    offset)))
+                       (list anchor node parent bol)))
+                     (offset-val
+                      (cond ((numberp offset) offset)
+                            ((and (symbolp offset)
+                                  (boundp offset))
+                             (symbol-value offset))
+                            (t (treesit--simple-indent-eval
+                                (list offset node parent bol))))))
+                 (cons anchor-pos offset-val))
                finally return
                (progn (when treesit--indent-verbose
                         (message "No matched rule"))
diff --git a/lisp/woman.el b/lisp/woman.el
index dfb5e69778..92cd425d32 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -2355,7 +2355,7 @@ Currently set only from \\='\\\" t in the first line of 
the source file.")
     (point-max)))
 
 (defun woman-horizontal-escapes (to)
-  "Process \\h'+/-N' local horizontal motion escapes upto TO.
+  "Process \\h'+/-N' local horizontal motion escapes up to TO.
 Implements arbitrary forward and non-overlapping backward motion.
 Preserves location of `point'."
   ;; Moved from `woman-decode-region' for version 0.50.
@@ -3346,7 +3346,7 @@ Ignore the default face and underline only word 
characters."
 
 (defun woman2-tr (to)
   ".tr abcde -- Translate a -> b, c -> d, ..., e -> space.
-Format paragraphs upto TO.  Supports special chars.
+Format paragraphs up to TO.  Supports special chars.
 \(Breaks, but should not.)"
   ;; This should be an update, but consing onto the front of the alist
   ;; has the same effect and match duplicates should not matter.
@@ -3402,7 +3402,7 @@ Format paragraphs upto TO.  Supports special chars.
 (defvar woman-registers                        ; these are all read-only
   '((".H" 24) (".V" 48)                        ; resolution in basic units
     (".g" 0)                           ; not groff
-    ;; (Iff emulating groff need to implement groff italic correction
+    ;; (If emulating groff need to implement groff italic correction
     ;; \/, e.g. for pic.1)
     (".i" left-margin)                 ; current indent
     (".j" woman-adjust)                        ; current adjustment
@@ -3432,7 +3432,7 @@ Handle numeric arguments specially if optional argument 
NUMERIC is non-nil."
 (defun woman2-nr (to)
   ".nr R +/-N M -- Assign +/-N (wrt to previous value, if any) to register R.
 The increment for auto-incrementing is set to M.
-Format paragraphs upto TO.  (Breaks, but should not!)"
+Format paragraphs up to TO.  (Breaks, but should not!)"
   (let* ((name (buffer-substring
                (point)
                (progn (skip-syntax-forward "^ ") (point))))
@@ -3699,7 +3699,7 @@ regexp, \"\\(\\\\c\\)?\\n[.\\=']\"."
 
 (defun woman2-PD (to)
   ".PD d -- Set the interparagraph distance to d.
-Round to whole lines, default 1 line.  Format paragraphs upto TO.
+Round to whole lines, default 1 line.  Format paragraphs up to TO.
 \(Breaks, but should not.)"
   ;; .ie \\n[.$] .nr PD (v;\\$1)
   ;; .el .nr PD .4v>?\n[.V]
@@ -3718,7 +3718,7 @@ Round to whole lines, default 1 line.  Format paragraphs 
upto TO.
   (setq woman-leave-blank-lines woman-interparagraph-distance))
 
 (defun woman2-TH (to)
-  ".TH n c x v m -- Begin a man page.  Format paragraphs upto TO.
+  ".TH n c x v m -- Begin a man page.  Format paragraphs up to TO.
 n is the name of the page in chapter c; x is extra commentary;
 v alters page foot left; m alters page head center.
 \(Should set prevailing indent and tabs to 5.)"
@@ -3748,7 +3748,7 @@ v alters page foot left; m alters page head center.
 
 (defun woman2-SH (to)
   ".SH -- Sub-head.  Leave blank line and subhead.
-Format paragraphs upto TO.  Set prevailing indent to 5."
+Format paragraphs up to TO.  Set prevailing indent to 5."
   (if (eolp)                           ; If no args then
       (delete-char 1)                  ; apply to next line
     (woman-unquote-args)               ; else unquote to end of heading
@@ -3767,7 +3767,7 @@ Format paragraphs upto TO.  Set prevailing indent to 5."
 
 (defun woman2-SS (to)
   ".SS -- Sub-sub-head.  Like .SH but indent heading 3 spaces.
-Format paragraphs upto TO."
+Format paragraphs up to TO."
   (if (eolp)                           ; If no args then
       (delete-char 1))                 ; apply to next line.
   (insert "   ")
@@ -3776,7 +3776,7 @@ Format paragraphs upto TO."
 
 (defun woman2-LP (to)
   ".LP,.PP -- Begin paragraph.  Set prevailing indent to 5.
-Leave 1 blank line.  Format paragraphs upto TO."
+Leave 1 blank line.  Format paragraphs up to TO."
   (woman-delete-line 1)                        ; ignore any arguments
   (woman-interparagraph-space)
   (setq woman-prevailing-indent woman-default-indent)
@@ -3786,21 +3786,21 @@ Leave 1 blank line.  Format paragraphs upto TO."
 (defalias 'woman2-P #'woman2-LP)
 
 (defun woman2-ns (to)
-  ".ns -- Turn on no-space mode.  Format paragraphs upto TO."
+  ".ns -- Turn on no-space mode.  Format paragraphs up to TO."
   ;; Should not cause a break!
   (woman-delete-line 1)                        ; ignore argument(s)
   (setq woman-nospace t)
   (woman2-format-paragraphs to))
 
 (defun woman2-rs (to)
-  ".rs -- Turn off no-space mode.  Format paragraphs upto TO."
+  ".rs -- Turn off no-space mode.  Format paragraphs up to TO."
   ;; Should not cause a break!
   (woman-delete-line 1)                        ; ignore argument(s)
   (setq woman-nospace nil)
   (woman2-format-paragraphs to))
 
 (defun woman2-sp (to)
-  ".sp N -- If N > 0 then leave 1 blank line.  Format paragraphs upto TO."
+  ".sp N -- If N > 0 then leave 1 blank line.  Format paragraphs up to TO."
   (let ((N (if (eolp) 1 (woman-get-numeric-arg))))
     (if (>= N 0)
        (woman-delete-line 1)           ; ignore argument(s)
@@ -3955,13 +3955,13 @@ Optional argument NUMERIC, if non-nil, means the 
argument is numeric."
 ;;; 4. Text Filling, Adjusting, and Centering
 
 (defun woman2-br (to)
-  ".br -- Break.  Leave no blank line.  Format paragraphs upto TO."
+  ".br -- Break.  Leave no blank line.  Format paragraphs up to TO."
   (woman-delete-line 1)                        ; ignore any arguments
   (woman2-format-paragraphs to))
 
 (defun woman2-fi (to)
   ".fi -- Fill subsequent output lines.  Leave no blank line.
-Format paragraphs upto TO."
+Format paragraphs up to TO."
   (setq woman-nofill nil)
   (woman-delete-line 1)                        ; ignore any arguments
   ;; Preserve any final blank line in the nofill region:
@@ -3981,7 +3981,7 @@ for the current line length.  Format paragraphs up to TO."
 (defun woman2-ad (to)
   ".ad c -- Line adjustment is begun (once fill mode is on).
 Set justification mode to c if specified.
-Format paragraphs upto TO.  (Breaks, but should not.)"
+Format paragraphs up to TO.  (Breaks, but should not.)"
   ;; c = l -- left, r -- right, c -- center, b or n -- both,
   ;; absent -- unchanged.  Initial mode adj,both.
   (setq woman-adjust
@@ -3997,7 +3997,7 @@ Format paragraphs upto TO.  (Breaks, but should not.)"
   (woman2-format-paragraphs to))
 
 (defun woman2-na (to)
-  ".na -- No adjusting.  Format paragraphs upto TO.
+  ".na -- No adjusting.  Format paragraphs up to TO.
 \(Breaks, but should not.)"
   (setq woman-adjust-previous woman-adjust
        woman-justify-previous woman-justify
@@ -4037,7 +4037,7 @@ non-nil and non-zero."
 (defvar woman-temp-indent nil)
 
 (defun woman2-format-paragraphs (to &optional new-left)
-  "Indent, fill and adjust paragraphs upto TO to current left margin.
+  "Indent, fill and adjust paragraphs up to TO to current left margin.
 If optional arg NEW-LEFT is non-nil then reset current left margin.
 If `woman-nofill' is non-nil then indent without filling or adjusting."
   ;; Blank space should only ever be output before text.
@@ -4103,7 +4103,7 @@ If `woman-nofill' is non-nil then indent without filling 
or adjusting."
 ;;; Tagged, indented and hanging paragraphs:
 
 (defun woman2-TP (to)
-  ".TP i -- Set prevailing indent to i.  Format paragraphs upto TO.
+  ".TP i -- Set prevailing indent to i.  Format paragraphs up to TO.
 Begin indented paragraph with hanging tag given by next text line.
 If tag doesn't fit, place it on a separate line."
   (let ((i (woman2-get-prevailing-indent)))
@@ -4111,7 +4111,7 @@ If tag doesn't fit, place it on a separate line."
     (woman2-tagged-paragraph to i)))
 
 (defun woman2-IP (to)
-  ".IP x i -- Same as .TP with tag x.  Format paragraphs upto TO."
+  ".IP x i -- Same as .TP with tag x.  Format paragraphs up to TO."
   (woman-interparagraph-space)
   (if (eolp)                           ; no args
       ;; Like LP without resetting prevailing indent
@@ -4152,7 +4152,7 @@ If tag doesn't fit, place it on a separate line."
 (defun woman2-tagged-paragraph (to i)
   "Begin indented paragraph with hanging tag given by current text line.
 If tag doesn't fit, leave it on separate line.
-Format paragraphs upto TO.  Set prevailing indent to I."
+Format paragraphs up to TO.  Set prevailing indent to I."
   (if (not (looking-at "\\s *$"))      ; non-empty tag
       (setq woman-leave-blank-lines nil))
 
@@ -4206,7 +4206,7 @@ Format paragraphs upto TO.  Set prevailing indent to I."
           (goto-char to)))))
 
 (defun woman2-HP (to)
-  ".HP i -- Set prevailing indent to i.  Format paragraphs upto TO.
+  ".HP i -- Set prevailing indent to i.  Format paragraphs up to TO.
 Begin paragraph with hanging indent."
   (let ((i (woman2-get-prevailing-indent)))
     (woman-interparagraph-space)
@@ -4228,7 +4228,7 @@ Delete line from point and eol unless LEAVE-EOL is 
non-nil."
 
 (defun woman2-RS (to)
   ".RS i -- Start relative indent, move left margin in distance i.
-Set prevailing indent to 5 for nested indents.  Format paragraphs upto TO."
+Set prevailing indent to 5 for nested indents.  Format paragraphs up to TO."
   (push woman-left-margin woman-RS-left-margin)
   (push woman-prevailing-indent woman-RS-prevailing-indent)
   (setq woman-left-margin (+ woman-left-margin
@@ -4237,7 +4237,7 @@ Set prevailing indent to 5 for nested indents.  Format 
paragraphs upto TO."
   (woman2-format-paragraphs to woman-left-margin))
 
 (defun woman2-RE (to)
-  ".RE -- End of relative indent.  Format paragraphs upto TO.
+  ".RE -- End of relative indent.  Format paragraphs up to TO.
 Set prevailing indent to amount of starting .RS."
   (when woman-RS-left-margin
     (setq woman-left-margin (pop woman-RS-left-margin)))
@@ -4274,18 +4274,18 @@ otherwise set PREVIOUS.  Delete the whole remaining 
control line."
 
 (defun woman2-ll (to)
   ".ll +/-N -- Set, increment or decrement line length.
-Format paragraphs upto TO.  (Breaks, but should not.)"
+Format paragraphs up to TO.  (Breaks, but should not.)"
   (woman-set-arg 'fill-column 'woman-ll-fill-column)
   (woman2-format-paragraphs to))
 
 (defun woman2-in (to)
   ".in +/-N -- Set, increment or decrement the indent.
-Format paragraphs upto TO."
+Format paragraphs up to TO."
   (woman-set-arg 'left-margin 'woman-in-left-margin)
   (woman2-format-paragraphs to))
 
 (defun woman2-ti (to)
-  ".ti +/-N -- Temporary indent.  Format paragraphs upto TO."
+  ".ti +/-N -- Temporary indent.  Format paragraphs up to TO."
   ;; Ignore if no argument.
   ;; Indent next output line only wrt current indent.
   ;; Current indent is not changed.
@@ -4300,7 +4300,7 @@ Format paragraphs upto TO."
   ".ta Nt ... -- Set tabs, left type, unless t=R(right), C(centered).
 \(Breaks, but should not.)  The tab stops are separated by spaces;
 a value preceded by + represents an increment to the previous stop value.
-Format paragraphs upto TO."
+Format paragraphs up to TO."
   (setq tab-stop-list nil)
   (woman2-process-escapes-to-eol 'numeric)
   (save-excursion
@@ -4350,7 +4350,7 @@ tab stop columns or pairs (COLUMN . TYPE) where TYPE is R 
or C."
       (insert ?\s))))
 
 (defun woman2-DT (to)
-  ".DT -- Restore default tabs.  Format paragraphs upto TO.
+  ".DT -- Restore default tabs.  Format paragraphs up to TO.
 \(Breaks, but should not.)"
   ;; Currently just terminates special tab processing.
   (setq tab-stop-list nil)
@@ -4359,7 +4359,7 @@ tab stop columns or pairs (COLUMN . TYPE) where TYPE is R 
or C."
 
 (defun woman2-fc (to)
   ".fc a b -- Set field delimiter a and pad character b.
-Format paragraphs upto TO.
+Format paragraphs up to TO.
 A VERY FIRST ATTEMPT to make fields at least readable!
 Needs doing properly!"
   (if (eolp)
@@ -4395,7 +4395,7 @@ Needs doing properly!"
 
 (defun woman2-TS (to)
   ".TS -- Start of table code for the tbl processor.
-Format paragraphs upto TO."
+Format paragraphs up to TO."
   (when woman-emulate-tbl
     ;; Assumes column separator is \t and intercolumn spacing is 3.
     ;; The first line may optionally be a list of options terminated by
diff --git a/src/ccl.c b/src/ccl.c
index c92684f4bc..6e780ef9f0 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -1987,7 +1987,7 @@ ccl_get_compiled_code (Lisp_Object ccl_prog, ptrdiff_t 
*idx)
 /* Setup fields of the structure pointed by CCL appropriately for the
    execution of CCL program CCL_PROG.  CCL_PROG is the name (symbol)
    of the CCL program or the already compiled code (vector).
-   Return true iff successful.
+   Return true if successful.
 
    If CCL_PROG is nil, just reset the structure pointed by CCL.  */
 bool
diff --git a/src/keyboard.c b/src/keyboard.c
index 306fea354e..990b5307f1 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -10128,7 +10128,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object 
prompt,
 
       if (/* first_unbound < indec.start && first_unbound < fkey.start && */
          first_unbound < keytran.start)
-       { /* The prefix upto first_unbound has no binding and has
+       { /* The prefix up to first_unbound has no binding and has
             no translation left to do either, so we know it's unbound.
             If we don't stop now, we risk staying here indefinitely
             (if the user keeps entering fkey or keytran prefixes
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index 6b2fa5df03..2dca0d16ad 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -223,7 +223,7 @@ typedef enum
           is followed by a range table:
               2 bytes of flags for character sets (low 8 bits, high 8 bits)
                   See RANGE_TABLE_WORK_BITS below.
-              2 bytes, the number of pairs that follow (upto 32767)
+              2 bytes, the number of pairs that follow (up to 32767)
               pairs, each 2 multibyte characters,
                   each multibyte character represented as 3 bytes.  */
   charset,
diff --git a/test/lisp/erc/resources/networks/merge-server/track.eld 
b/test/lisp/erc/resources/networks/merge-server/track.eld
index 4a97f92f72..19c37aaf40 100644
--- a/test/lisp/erc/resources/networks/merge-server/track.eld
+++ b/test/lisp/erc/resources/networks/merge-server/track.eld
@@ -21,7 +21,7 @@
  (0.00 ":irc.example.net 376 tester :End of message of the day."))
 
 ((mode 10 "MODE tester +i")
- (0.00 ":irc.example.net 501 tester x :is not a recognised user mode.")
+ (0.00 ":irc.example.net 501 tester x :is not a recognized user mode.")
  (0.00 ":NickServ!NickServ@services.int NOTICE tester :Welcome to FooNet, 
tester! Here on FooNet, we provide services to enable the registration of 
nicknames and channels! For details, type \2/msg NickServ help\2 and \2/msg 
ChanServ help\2.")
  (0.02 ":tester!user@10.0.2.100 MODE tester :+i"))
 
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 2ac5e0f29d..1de8e56cbd 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -421,7 +421,7 @@
       (switch-to-completions)
       ;; Fixed in bug#55430
       (should (equal "aa" (get-text-property (point) 'completion--string)))
-      (next-completion 3)
+      (next-completion 2)
       (should (equal "ac" (get-text-property (point) 'completion--string)))
       (previous-completion 2)
       (should (equal "aa" (get-text-property (point) 'completion--string)))
diff --git a/test/lisp/net/tramp-archive-tests.el 
b/test/lisp/net/tramp-archive-tests.el
index 85766f95cd..59b7ed9cf7 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -872,7 +872,7 @@ This tests also `file-executable-p', `file-writable-p' and 
`set-file-modes'."
   (let ((fsi (file-system-info tramp-archive-test-archive)))
     (skip-unless fsi)
     (should (and (consp fsi)
-                (= (length fsi) 3)
+                (tramp-compat-length= fsi 3)
                 (numberp (nth 0 fsi))
                 ;; FREE and AVAIL are always 0.
                 (zerop (nth 1 fsi))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 918929f55e..168933b6b4 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -4516,17 +4516,17 @@ This tests also `make-symbolic-link', `file-truename' 
and `add-name-to-file'."
                  (and (string-match-p tramp-ipv6-regexp host)
                       tramp-postfix-ipv6-format)))
               ;; Complete method name.
-             (unless (or (zerop (length method))
-                          (zerop (length tramp-method-regexp)))
+             (unless (or (tramp-string-empty-or-nil-p method)
+                          (string-empty-p tramp-method-regexp))
                (should
                 (member
                  (concat prefix-format method tramp-postfix-method-format)
                  (file-name-all-completions
                    (concat prefix-format (substring method 0 1)) "/"))))
               ;; Complete host name.
-             (unless (or (zerop (length method))
-                          (zerop (length tramp-method-regexp))
-                          (zerop (length host))
+             (unless (or (tramp-string-empty-or-nil-p method)
+                          (string-empty-p tramp-method-regexp)
+                          (tramp-string-empty-or-nil-p host)
                          (tramp--test-gvfs-p method))
                (should
                 (member
@@ -4852,8 +4852,8 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
        ;; Cleanup.
        (ignore-errors (delete-process proc)))
 
-      ;; Disabled process filter.  "sshfs" does not cooperate.
-      (unless (tramp--test-sshfs-p)
+      ;; Disabled process filter.  It doesn't work reliable.
+      (unless t
        (unwind-protect
            (with-temp-buffer
              (setq command '("cat")
@@ -5046,8 +5046,8 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
        ;; Cleanup.
        (ignore-errors (delete-process proc)))
 
-      ;; Disabled process filter.  "sshfs" does not cooperate.
-      (unless (tramp--test-sshfs-p)
+      ;; Disabled process filter.  It doesn't work reliable.
+      (unless t
        (unwind-protect
            (with-temp-buffer
              (setq command '("cat")
@@ -5370,7 +5370,7 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
   (when-let ((default-directory ert-remote-temporary-file-directory)
              (mi (memory-info)))
     (should (consp mi))
-    (should (= (length mi) 4))
+    (should (tramp-compat-length= mi 4))
     (dotimes (i (length mi))
       (should (natnump (nth i mi))))))
 
@@ -5915,7 +5915,8 @@ INPUT, if non-nil, is a string sent to the process."
           ;; We make a super long `tramp-remote-path'.
           (make-directory tmp-name)
           (should (file-directory-p tmp-name))
-          (while (< (length (mapconcat #'identity orig-exec-path ":")) 5000)
+          (while (tramp-compat-length<
+                 (mapconcat #'identity orig-exec-path ":") 5000)
             (let ((dir (make-temp-file (file-name-as-directory tmp-name) 
'dir)))
               (should (file-directory-p dir))
               (setq tramp-remote-path
@@ -5931,9 +5932,10 @@ INPUT, if non-nil, is a string sent to the process."
           ;; Ignore trailing newline.
          (setq path (substring (shell-command-to-string "echo $PATH") nil -1))
          ;; The shell doesn't handle such long strings.
-         (when (<= (length path)
-                   (tramp-get-connection-property
-                    tramp-test-vec "pipe-buf" 4096))
+         (unless (tramp-compat-length>
+                  path
+                  (tramp-get-connection-property
+                   tramp-test-vec "pipe-buf" 4096))
            ;; The last element of `exec-path' is `exec-directory'.
             (should
             (string-equal
@@ -7070,7 +7072,7 @@ This requires restrictions of file name syntax."
 
   (when-let ((fsi (file-system-info ert-remote-temporary-file-directory)))
     (should (consp fsi))
-    (should (= (length fsi) 3))
+    (should (tramp-compat-length= fsi 3))
     (dotimes (i (length fsi))
       (should (natnump (or (nth i fsi) 0))))))
 
diff --git a/test/lisp/progmodes/c-ts-mode-resources/filling.erts 
b/test/lisp/progmodes/c-ts-mode-resources/filling.erts
new file mode 100644
index 0000000000..e51e3658c8
--- /dev/null
+++ b/test/lisp/progmodes/c-ts-mode-resources/filling.erts
@@ -0,0 +1,198 @@
+Code:
+  (lambda ()
+    (c-ts-mode)
+    (setq-local indent-tabs-mode nil)
+    (fill-paragraph))
+
+Point-Char: |
+
+Name: Type 1
+
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=-=
+
+Name: Type 2
+
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=-=
+
+Name: Type 3
+
+=-=
+/*================================================================
+  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+  woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+  woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+  ================================================================*/
+=-=
+/*================================================================
+  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+  woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+  ================================================================*/
+=-=-=
+
+Name: Type 4
+
+=-=
+/*================================================================
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ woooomy woooomy woooomy woooomy woooomy
+ * ================================================================*/
+=-=
+/*================================================================
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy
+ * ================================================================*/
+=-=-=
+
+Name: Type 5
+
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ * woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=-=
+
+Name: Type 6
+
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=-=
+
+Name: Type 6
+
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+ */
+=-=-=
+
+Name: Type 7
+
+=-=
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+=-=
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+=-=-=
+
+Name: Type 8
+
+=-=
+// ================================================================
+//  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+//  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+//  woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+//  ================================================================
+=-=
+// ================================================================
+//  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+//  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+//  woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+//  ================================================================
+=-=-=
+
+Name: Type 9
+
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomyyy  */
+=-=
+/* woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+   woooomyyy  */
+=-=-=
+
+Name: Not Over Fill 1
+
+=-=
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+
+// |woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+=-=-=
+
+Name: Not Over Fill 2
+
+=-=
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+return; // woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+//| woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+return; // woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+=-=
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+return; // woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+return; // woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+=-=-=
+
+Name: Not Over Fill 3
+
+=-=
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+return; //| woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+return; // woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+=-=
+// woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+return; // woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+        // woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+        // woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+        // woooomy woooomy
+return; // woooomy woooomy woooomy woooomy woooomy woooomy woooomy woooomy
+=-=-=
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts 
b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
index 5defcbd3c8..71524e273f 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
@@ -1,8 +1,13 @@
 Code:
   (lambda ()
+    (setq indent-tabs-mode nil)
+    (setq c-ts-mode-indent-offset 2)
+    (setq c-ts-mode-indent-style 'gnu)
     (c-ts-mode)
     (indent-region (point-min) (point-max)))
 
+Point-Char: |
+
 Name: Basic
 
 =-=
@@ -25,6 +30,68 @@ main (void)
 }
 =-=-=
 
+Name: Labels (GNU Style)
+
+=-=
+int
+main (void)
+{
+ label:
+  return 0;
+  if (true)
+    {
+    label:
+      return 0;
+    }
+  else
+    {
+      if (true)
+        {
+        label:
+          return 0;
+        }
+    }
+}
+=-=-=
+
+Name: For Loop with Multi-line Condition (GNU Style)
+
+=-=
+int main()
+{
+  for (int i = 0;
+       i < b;
+       i++)
+    {
+      return 0;
+    }
+}
+=-=-=
+
+Name: If-Else (GNU Style)
+
+=-=
+int main()
+{
+  if (true)
+    {
+      return 0;
+    }
+  else
+    {
+      return 1;
+    }
+}
+=-=-=
+
+Name: Empty Line
+=-=
+int main()
+{
+  |
+}
+=-=-=
+
 Name: Multiline Parameter List (bug#60398)
 
 =-=
@@ -34,7 +101,7 @@ int f2(int x,
 };
 =-=-=
 
-Name: Multiline Block Comments (bug#60270)
+Name: Multiline Block Comments 1 (bug#60270)
 
 =-=
 /**
@@ -42,3 +109,55 @@ Name: Multiline Block Comments (bug#60270)
  * @arg1:
  */
 =-=-=
+
+Name: Multiline Block Comments 2 (bug#60270)
+
+=-=
+/*
+  some comment
+ */
+=-=-=
+
+Name: Multiline Block Comments 3 (bug#60270)
+
+=-=
+/* some comment
+ */
+=-=-=
+
+Name: Multiline Block Comments 4 (bug#60270)
+
+=-=
+/*
+ * Some comment
+ */
+=-=-=
+
+
+Code:
+  (lambda ()
+    (setq indent-tabs-mode nil)
+    (setq c-ts-mode-indent-offset 8)
+    (setq c-ts-mode-indent-style 'linux)
+    (c-ts-mode)
+    (indent-region (point-min) (point-max)))
+
+Name: Labels (Linux Style)
+
+=-=-=
+int main (void)
+{
+label:
+        return 0;
+        if (true) {
+label:
+                return 0;
+        }
+        else {
+                if (true) {
+label:
+                        return 0;
+                }
+        }
+}
+=-=-=
diff --git a/test/lisp/progmodes/c-ts-mode-tests.el 
b/test/lisp/progmodes/c-ts-mode-tests.el
index 8606faf991..3d0902fe50 100644
--- a/test/lisp/progmodes/c-ts-mode-tests.el
+++ b/test/lisp/progmodes/c-ts-mode-tests.el
@@ -27,5 +27,9 @@
   (skip-unless (treesit-ready-p 'c))
   (ert-test-erts-file (ert-resource-file "indent.erts")))
 
+(ert-deftest c-ts-mode-test-filling ()
+  (skip-unless (treesit-ready-p 'c))
+  (ert-test-erts-file (ert-resource-file "filling.erts")))
+
 (provide 'c-ts-mode-tests)
 ;;; c-ts-mode-tests.el ends here
diff --git a/test/manual/indent/octave.m b/test/manual/indent/octave.m
index 76cad09ad1..08b7fa58d5 100644
--- a/test/manual/indent/octave.m
+++ b/test/manual/indent/octave.m
@@ -1517,7 +1517,7 @@ function copy_files (desc, packdir, global_install)
     if (exist (fullfile (desc.dir, getarch ()), "dir") &&
        ! strcmp (fullfile (desc.dir, getarch ()), octfiledir))
       if (! exist (octfiledir, "dir"))
-        ## Can be required to create upto three levels of dirs.
+        ## Can be required to create up to three levels of dirs.
         octm1 = fileparts (octfiledir);
         if (! exist (octm1, "dir"))
           octm2 = fileparts (octm1);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]