emacs-diffs
[Top][All Lists]
Advanced

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

master 7d12c06: Merge from origin/emacs-28


From: Glenn Morris
Subject: master 7d12c06: Merge from origin/emacs-28
Date: Mon, 18 Oct 2021 10:57:22 -0400 (EDT)

branch: master
commit 7d12c06725d733f1ea223f5fe55d506c71e44370
Merge: a6f156a c163fd9
Author: Glenn Morris <rgm@gnu.org>
Commit: Glenn Morris <rgm@gnu.org>

    Merge from origin/emacs-28
    
    c163fd9260 (origin/emacs-28) Minor fixes for recent changes in ELisp ...
    fefada4816 Fix example in calc manual
    e74e17c1f0 Rewrites of Elisp manual including tab-bar and tab-line ch...
    3b138917b7 ; * INSTALL: Fix typo.
    ce71446585 * lisp/tab-bar.el: Improve docstrings (bug#51247)
    ace4ce16a3 * lisp/tab-bar.el (tab-bar-mouse-move-tab): Don't drag tab...
    04716ca48f Add tab-bar-drag-maybe for indication of tab dragging (bug...
    81e3697600 * lisp/tab-bar.el: Add a new tab on [mouse-1] instead of [...
    a191d3c725 Add new and fix existing docstrings in tab-bar.el and tab-...
    77dbaedadc Add tab bar support to the nextstep port
    7b6fb486c2 Fix potential buffer overflow (bug#50767)
    ed9f5546aa Improve doc strings in tab-line.el
    686a03ee22 More documentation fixes in tab-bar.el
    35920791df Improve doc strings of tab-bar commands
    2d15db6e89 Fix a semantic test on some macOS machines
    ac6ac76e3a Update to Org 9.5-57-g9bc3a2
---
 INSTALL                                      |   2 +-
 doc/lispref/buffers.texi                     |  44 +-
 doc/lispref/elisp.texi                       |   2 +-
 doc/lispref/frames.texi                      |  39 +-
 doc/lispref/objects.texi                     |  21 +-
 doc/lispref/spellfile                        |  18 +
 doc/lispref/windows.texi                     | 820 +++++++++++++++------------
 doc/misc/calc.texi                           |   2 +-
 etc/ORG-NEWS                                 |   9 +
 lisp/org/oc-basic.el                         |   1 -
 lisp/org/oc-biblatex.el                      |   4 +-
 lisp/org/oc-csl.el                           |  21 +-
 lisp/org/oc.el                               |  36 +-
 lisp/org/org-version.el                      |   2 +-
 lisp/org/org.el                              |   1 +
 lisp/tab-bar.el                              | 245 +++++---
 lisp/tab-line.el                             |  96 ++--
 src/image.c                                  |  23 +-
 src/nsfns.m                                  |  63 +-
 src/nsterm.h                                 |   1 +
 src/nsterm.m                                 |  42 +-
 src/window.c                                 |  25 +-
 src/xdisp.c                                  |  12 +-
 test/lisp/cedet/semantic/bovine/gcc-tests.el |   7 +-
 24 files changed, 929 insertions(+), 607 deletions(-)

diff --git a/INSTALL b/INSTALL
index 8c036f2..6207f43 100644
--- a/INSTALL
+++ b/INSTALL
@@ -220,7 +220,7 @@ GNU/Linux distribution that you use, and the options that 
you want to
 configure Emacs with.  On Debian-based systems, you can install all the
 packages needed to build the installed version of Emacs with a command
 like 'apt-get build-dep emacs' (on older systems, replace 'emacs' with
-eg 'emacs25').  On Red Hat-based systems, the corresponding command is
+e.g. 'emacs25').  On Red Hat-based systems, the corresponding command is
 'dnf builddep emacs' (on older systems, use 'yum-builddep' instead).
 
 On FreeBSD, the command is 'pkg install -y `pkg rquery %dn emacs-devel`'.
diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi
index 55e9d00..6a0095d 100644
--- a/doc/lispref/buffers.texi
+++ b/doc/lispref/buffers.texi
@@ -89,11 +89,12 @@ in which most editing takes place.  Most of the primitives 
for
 examining or changing text operate implicitly on the current buffer
 (@pxref{Text}).
 
-  Normally, the buffer displayed in the selected window is the current
-buffer, but this is not always so: a Lisp program can temporarily
-designate any buffer as current in order to operate on its contents,
-without changing what is displayed on the screen.  The most basic
-function for designating a current buffer is @code{set-buffer}.
+  Normally, the buffer displayed in the selected window
+(@pxref{Selecting Windows}) is the current buffer, but this is not
+always so: a Lisp program can temporarily designate any buffer as
+current in order to operate on its contents, without changing what is
+displayed on the screen.  The most basic function for designating a
+current buffer is @code{set-buffer}.
 
 @defun current-buffer
 This function returns the current buffer.
@@ -118,12 +119,12 @@ on it.
 
   When an editing command returns to the editor command loop, Emacs
 automatically calls @code{set-buffer} on the buffer shown in the
-selected window.  This is to prevent confusion: it ensures that the
-buffer that the cursor is in, when Emacs reads a command, is the
-buffer to which that command applies (@pxref{Command Loop}).  Thus,
-you should not use @code{set-buffer} to switch visibly to a different
-buffer; for that, use the functions described in @ref{Switching
-Buffers}.
+selected window (@pxref{Selecting Windows}).  This is to prevent
+confusion: it ensures that the buffer that the cursor is in, when Emacs
+reads a command, is the buffer to which that command applies
+(@pxref{Command Loop}).  Thus, you should not use @code{set-buffer} to
+switch visibly to a different buffer; for that, use the functions
+described in @ref{Switching Buffers}.
 
   When writing a Lisp function, do @emph{not} rely on this behavior of
 the command loop to restore the current buffer after an operation.
@@ -912,16 +913,17 @@ History}) provided it is shown in that window.
 
 If @var{buffer-or-name} is @code{nil} or omitted, this means to bury the
 current buffer.  In addition, if the current buffer is displayed in the
-selected window, this makes sure that the window is either deleted or
-another buffer is shown in it.  More precisely, if the selected window
-is dedicated (@pxref{Dedicated Windows}) and there are other windows on
-its frame, the window is deleted.  If it is the only window on its frame
-and that frame is not the only frame on its terminal, the frame is
-dismissed by calling the function specified by
-@code{frame-auto-hide-function} (@pxref{Quitting Windows}).  Otherwise,
-it calls @code{switch-to-prev-buffer} (@pxref{Window History}) to show
-another buffer in that window.  If @var{buffer-or-name} is displayed in
-some other window, it remains displayed there.
+selected window (@pxref{Selecting Windows}), this makes sure that the
+window is either deleted or another buffer is shown in it.  More
+precisely, if the selected window is dedicated (@pxref{Dedicated
+Windows}) and there are other windows on its frame, the window is
+deleted.  If it is the only window on its frame and that frame is not
+the only frame on its terminal, the frame is dismissed by calling the
+function specified by @code{frame-auto-hide-function} (@pxref{Quitting
+Windows}).  Otherwise, it calls @code{switch-to-prev-buffer}
+(@pxref{Window History}) to show another buffer in that window.  If
+@var{buffer-or-name} is displayed in some other window, it remains
+displayed there.
 
 To replace a buffer in all the windows that display it, use
 @code{replace-buffer-in-windows}, @xref{Buffers and Windows}.
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index da3a3a8..c4bd97b 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -1048,6 +1048,7 @@ Windows
 
 * Basic Windows::           Basic information on using windows.
 * Windows and Frames::      Relating windows to the frame they appear on.
+* Selecting Windows::       The selected window is the one that you edit in.
 * Window Sizes::            Accessing a window's size.
 * Resizing Windows::        Changing the sizes of windows.
 * Preserving Window Sizes:: Preserving the size of windows.
@@ -1055,7 +1056,6 @@ Windows
 * Deleting Windows::        Deleting a window gives its space to other windows.
 * Recombining Windows::     Preserving the frame layout when splitting and
                               deleting windows.
-* Selecting Windows::       The selected window is the one that you edit in.
 * Cyclic Window Ordering::  Moving around the existing windows.
 * Buffers and Windows::     Each window displays the contents of a buffer.
 * Switching Buffers::       Higher-level functions for switching to a buffer.
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 477c105..f851d12 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -151,7 +151,7 @@ the window (a.k.a.@: the @dfn{dominating} monitor).
 
 This function itself does not make the new frame the selected frame.
 @xref{Input Focus}.  The previously selected frame remains selected.
-On graphical terminals, however, the windowing system may select the
+On graphical terminals, however, the window system may select the
 new frame for its own reasons.
 @end deffn
 
@@ -494,7 +494,8 @@ a graphical terminal:
      | |  |_____________ Title Bar ______________|  |
      | | (1)_____________ Menu Bar ______________|  | ^
      | | (2)_____________ Tool Bar ______________|  | ^
-     | | (3) _________ Internal Border ________  |  | ^
+     | | (3)_____________ Tab Bar _______________|  | ^
+     | |  |  _________ Internal Border ________  |  | ^
      | |  | |   ^                              | |  | |
      | |  | |   |                              | |  | |
 Outer  |  | | Inner                            | |  | Native
@@ -640,6 +641,15 @@ GTK+, on the other hand, never wraps the tool bar but may
 automatically increase the outer width of a frame in order to
 accommodate an overlong tool bar.
 
+@item Tab Bar
+@cindex internal tab bar
+The tab bar (@pxref{Tab Bars,,,emacs, The GNU Emacs Manual}) is always
+drawn by Emacs itself.  The tab bar appears above the tool bar in
+Emacs built with an internal tool bar, and below the tool bar in
+builds with an external tool bar.
+Display of the tab bar can be suppressed by setting the
+@code{tab-bar-lines} parameter (@pxref{Layout Parameters}) to zero.
+
 @item Native Frame
 @cindex native frame
 @cindex native edges
@@ -740,8 +750,8 @@ the internal border, one vertical scroll bar, and one left 
and one right
 fringe if they are specified for this frame, see @ref{Layout
 Parameters}.  Its height can be obtained by removing from that of the
 native height the widths of the internal border and the heights of the
-frame's internal menu and tool bars and one horizontal scroll bar if
-specified for this frame.
+frame's internal menu and tool bars, the tab bar and one horizontal
+scroll bar if specified for this frame.
 @end table
 
 @cindex absolute position
@@ -1875,6 +1885,13 @@ The position of the tool bar when Emacs was built with 
GTK+.  Its value
 can be one of @code{top}, @code{bottom} @code{left}, @code{right}.  The
 default is @code{top}.
 
+@vindex tab-bar-lines@r{, a frame parameter}
+@item tab-bar-lines
+The number of lines to use for the tab bar (@pxref{Tab Bars,,,emacs, The
+GNU Emacs Manual}).  The default is one if Tab Bar mode is enabled and
+zero otherwise.  This value may change whenever the tab bar wraps
+(@pxref{Frame Layout}).
+
 @vindex line-spacing@r{, a frame parameter}
 @item line-spacing
 Additional space to leave below each text line, in pixels (a positive
@@ -2758,7 +2775,8 @@ Terminals}.
 @cindex selected frame
 
 At any time, one frame in Emacs is the @dfn{selected frame}.  The
-selected window always resides on the selected frame.
+selected window (@pxref{Selecting Windows}) always resides on the
+selected frame.
 
 When Emacs displays its frames on several terminals (@pxref{Multiple
 Terminals}), each terminal has its own selected frame.  But only one
@@ -2992,12 +3010,11 @@ Auto-selection}).
 
 Note that this option does not distinguish ``sloppy'' focus (where the
 frame that previously had focus retains focus as long as the mouse
-pointer does not move into another window manager window) from
-``strict'' focus (where a frame immediately loses focus when it's left
-by the mouse pointer).  Neither does it recognize whether your window
-manager supports delayed focusing or auto-raising where you can
-explicitly specify the time until a new frame gets focus or is
-auto-raised.
+pointer does not move into another window-system window) from ``strict''
+focus (where a frame immediately loses focus when it's left by the mouse
+pointer).  Neither does it recognize whether your window manager
+supports delayed focusing or auto-raising where you can explicitly
+specify the time until a new frame gets focus or is auto-raised.
 
 You can supply a ``focus follows mouse'' policy for individual Emacs
 windows by customizing the variable @code{mouse-autoselect-window}
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index a20343f..0551bb5 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -1625,19 +1625,18 @@ markers.
 @node Window Type
 @subsection Window Type
 
-  A @dfn{window} describes the portion of the terminal screen that Emacs
-uses to display a buffer.  Every window has one associated buffer, whose
-contents appear in the window.  By contrast, a given buffer may appear
-in one window, no window, or several windows.
+  A @dfn{window} describes the portion of the screen that Emacs uses to
+display buffers.  Every live window (@pxref{Basic Windows}) has one
+associated buffer, whose contents appear in that window.  By contrast, a
+given buffer may appear in one window, no window, or several windows.
+Windows are grouped on the screen into frames; each window belongs to
+one and only one frame.  @xref{Frame Type}.
 
   Though many windows may exist simultaneously, at any time one window
-is designated the @dfn{selected window}.  This is the window where the
-cursor is (usually) displayed when Emacs is ready for a command.  The
-selected window usually displays the current buffer (@pxref{Current
-Buffer}), but this is not necessarily the case.
-
-  Windows are grouped on the screen into frames; each window belongs to
-one and only one frame.  @xref{Frame Type}.
+is designated the @dfn{selected window} (@pxref{Selecting Windows}).
+This is the window where the cursor is (usually) displayed when Emacs is
+ready for a command.  The selected window usually displays the current
+buffer (@pxref{Current Buffer}), but this is not necessarily the case.
 
   Windows have no read syntax.  They print in hash notation, giving the
 window number and the name of the buffer being displayed.  The window
diff --git a/doc/lispref/spellfile b/doc/lispref/spellfile
index 45a122d..11a6ce8 100644
--- a/doc/lispref/spellfile
+++ b/doc/lispref/spellfile
@@ -179,6 +179,8 @@ copyleft
 counterintuitive
 cr
 creatable
+customization
+customizations
 customize
 deactivate
 deactivated
@@ -243,6 +245,8 @@ fmakunbound
 fo
 fol
 following'
+fontification
+fontified
 fooba
 foobaz
 foox
@@ -257,6 +261,7 @@ garbles
 gc
 getenv
 gid
+glyphs
 gp
 grep
 gtr
@@ -270,6 +275,8 @@ hostname
 hpux
 hscroll
 ick
+iconified
+iconify
 id
 idiom
 ii
@@ -314,6 +321,7 @@ mathsurround
 memq
 mh
 mini
+minibuf
 minibuffer's
 minibuffers
 misalignment
@@ -387,6 +395,7 @@ passwd
 ped
 perverse
 pid
+pixelwise
 plist
 pointer'
 pointm
@@ -417,6 +426,10 @@ reader'
 rebind
 rec
 rechecking
+redisplay
+redisplayed
+redisplaying
+redisplays
 redo
 redrawing
 redraws
@@ -430,6 +443,7 @@ reinitialize
 reinitialized
 reinstall
 reinstalled
+resizable
 resize
 resized
 resizes
@@ -486,6 +500,8 @@ terpri
 text'
 tildes
 time's
+tooltip
+tooltips
 towards
 transportable
 txt
@@ -494,6 +510,7 @@ unbind
 unbinding
 unbinds
 unclutters
+uncustomized
 undefine
 undefines
 underfull
@@ -520,6 +537,7 @@ vconcat
 vectorp
 vn
 voidness
+whitespace
 window'
 windowing
 windowp
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index d015ac1..fb72b8f 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -14,6 +14,7 @@ is displayed in windows.
 @menu
 * Basic Windows::           Basic information on using windows.
 * Windows and Frames::      Relating windows to the frame they appear on.
+* Selecting Windows::       The selected window is the one that you edit in.
 * Window Sizes::            Accessing a window's size.
 * Resizing Windows::        Changing the sizes of windows.
 * Preserving Window Sizes:: Preserving the size of windows.
@@ -21,7 +22,6 @@ is displayed in windows.
 * Deleting Windows::        Removing a window from its frame.
 * Recombining Windows::     Preserving the frame layout when splitting and
                               deleting windows.
-* Selecting Windows::       The selected window is the one that you edit in.
 * Cyclic Window Ordering::  Moving around the existing windows.
 * Buffers and Windows::     Each window displays the contents of a buffer.
 * Switching Buffers::       Higher-level functions for switching to a buffer.
@@ -53,32 +53,37 @@ is displayed in windows.
 @section Basic Concepts of Emacs Windows
 @cindex window
 
-A @dfn{window} is an area of the screen that is used to display a buffer
-(@pxref{Buffers}).  In Emacs Lisp, windows are represented by a special
-Lisp object type.
-
 @cindex multiple windows
-  Windows are grouped into frames (@pxref{Frames}).  Each frame
-contains at least one window; the user can subdivide it into multiple,
-non-overlapping windows to view several buffers at once.  Lisp
-programs can use multiple windows for a variety of purposes.  In
-Rmail, for example, you can view a summary of message titles in one
-window, and the contents of the selected message in another window.
+A @dfn{window} is an area of the screen that can be used to display a
+buffer (@pxref{Buffers}).  Windows are grouped into frames
+(@pxref{Frames}).  Each frame contains at least one window; the user can
+subdivide a frame into multiple, non-overlapping windows to view several
+buffers at once.  Lisp programs can use multiple windows for a variety
+of purposes.  In Rmail, for example, you can view a summary of message
+titles in one window, and the contents of the selected message in
+another window.
 
 @cindex terminal screen
 @cindex screen of terminal
-  Emacs uses the word ``window'' with a different meaning than in
-graphical desktop environments and window systems, such as the X
-Window System.  When Emacs is run on X, each of its graphical X
-windows is an Emacs frame (containing one or more Emacs windows).
-When Emacs is run on a text terminal, the frame fills the entire
-terminal screen.
+@cindex window-system window
+  Emacs uses the term ``window'' with a different meaning than in
+graphical desktop environments and window systems, such as the X Window
+System.  When Emacs is run on X, each graphical X window owned by the
+Emacs process corresponds to one Emacs frame.  When Emacs is run on a
+text terminal, each Emacs frame fills the entire terminal screen.  In
+either case, the frame may contain one or more Emacs windows.  For
+disambiguation, we use the term @dfn{window-system window} when we mean
+the window-system window corresponding to an Emacs frame.
 
 @cindex tiled windows
   Unlike X windows, Emacs windows are @dfn{tiled}; they never overlap
-within the area of the frame.  When a window is created, resized, or
-deleted, the change in window space is taken from or given to the
-adjacent windows, so that the total area of the frame is unchanged.
+within the area of their frame.  When a window is created, resized, or
+deleted, the change in window space is taken from or given to other
+windows on the same frame, so that the total area of the frame is
+unchanged.
+
+In Emacs Lisp, windows are represented by a special Lisp object type
+(@pxref{Window Type}).
 
 @defun windowp object
 This function returns @code{t} if @var{object} is a window (whether or
@@ -117,94 +122,148 @@ internal window in a window tree.  Otherwise, it returns 
@code{nil},
 including for the case where @var{object} is a deleted window.
 @end defun
 
-@cindex selected window
-@cindex window selected within a frame
-  In each frame, at any time, exactly one Emacs window is designated
-as @dfn{selected within the frame}.  For the selected frame, that
-window is called the @dfn{selected window}---the one in which most
-editing takes place, and in which the cursor for selected windows
-appears (@pxref{Cursor Parameters}).  Keyboard input that inserts or
-deletes text is also normally directed to this window.   The selected
-window's buffer is usually also the current buffer, except when
-@code{set-buffer} has been used (@pxref{Current Buffer}).  As for
-non-selected frames, the window selected within the frame becomes the
-selected window if the frame is ever selected.  @xref{Selecting
-Windows}.
+  The following schematic shows the structure of a live window:
 
-@defun selected-window
-This function returns the selected window (which is always a live
-window).
-@end defun
+@smallexample
+@group
+        ____________________________________________
+       |________________ Tab Line _______________|RD| ^
+       |______________ Header Line ______________|  | |
+     ^ |LS|LM|LF|                       |RF|RM|RS|  | |
+     | |  |  |  |                       |  |  |  |  | |
+Window |  |  |  |       Text Area       |  |  |  |  | Window
+Body | |  |  |  |     (Window Body)     |  |  |  |  | Total
+Height |  |  |  |                       |  |  |  |  | Height
+     | |  |  |  |<- Window Body Width ->|  |  |  |  | |
+     v |__|__|__|_______________________|__|__|__|  | |
+       |_________ Horizontal Scroll Bar _________|  | |
+       |_______________ Mode Line _______________|__| |
+       |_____________ Bottom Divider _______________| v
+        <---------- Window Total Width ------------>
 
-@anchor{Window Group}Sometimes several windows collectively and
-cooperatively display a buffer, for example, under the management of
-Follow Mode (@pxref{Follow Mode,,, emacs}), where the windows together
-display a bigger portion of the buffer than one window could alone.
-It is often useful to consider such a @dfn{window group} as a single
-entity.  Several functions such as @code{window-group-start}
-(@pxref{Window Start and End}) allow you to do this by supplying, as
-an argument, one of the windows as a stand in for the whole group.
+@end group
+@end smallexample
 
-@defun selected-window-group
-@vindex selected-window-group-function
-When the selected window is a member of a group of windows, this
-function returns a list of the windows in the group, ordered such that
-the first window in the list is displaying the earliest part of the
-buffer, and so on.  Otherwise the function returns a list containing
-just the selected window.
+@cindex window body
+@cindex text area of a window
+@cindex body of a window
+@cindex window decorations
+@cindex left and right window decorations
+@cindex top and bottom window decorations
+  At the center of that window is the @dfn{text area}, or @dfn{body},
+where the buffer text is displayed.  The text area can be surrounded by
+a series of optional areas which we will call @dfn{window decorations}.
+On the left and right, from innermost to outermost, these are the left
+and right fringes, denoted by LF and RF (@pxref{Fringes}); the left and
+right margins, denoted by LM and RM in the schematic (@pxref{Display
+Margins}); the left or right vertical scroll bar, only one of which is
+present at any time, denoted by LS and RS (@pxref{Scroll Bars}); and the
+right divider, denoted by RD (@pxref{Window Dividers}).  Together these
+are the window's @dfn{left and right decorations}.
+
+  At the top of the window are the tab line and the header line
+(@pxref{Header Lines}).  At the bottom of the window are the horizontal
+scroll bar (@pxref{Scroll Bars}); the mode line (@pxref{Mode Line
+Format}); and the bottom divider (@pxref{Window Dividers}).  Together
+these form the window's @dfn{top and bottom decorations}.
+
+  There are two special areas omitted in the schematic:
+
+@itemize @bullet
+@item
+When any of the fringes is missing, the display engine may use one
+character cell in its place for showing a continuation or truncation
+glyph provided a text line doesn't fit in a window.
+
+@item
+When both, the vertical scroll bar and the right divider are missing,
+the display engine usurps one pixel for drawing a vertical divider line
+between this window and the window on its right, provided such a window
+exists.  On a text terminal, this divider always occupies an entire
+character cell.
+@end itemize
+
+In either case, the resulting artifact is considered part of the
+window's body although its screen space cannot be used for displaying
+buffer text.
+
+  Note also, that line numbers (and their surrounding whitespace) as
+displayed by @code{display-line-numbers-mode} (@pxref{Display Custom,,,
+emacs, The GNU Emacs Manual}) do not count as decorations either; they
+are part of the window's body too.
+
+  Internal windows neither show any text nor do they have decorations.
+Hence, the concept of ``body'' does not make sense for them.  In fact,
+most functions operating on the body of a window will yield an error
+when applied to an internal window.
+
+@cindex minibuffer window
+@cindex tooltip window
+  By default, an Emacs frame exhibits one special live window that is
+used for displaying messages and accepting user input---the
+@dfn{minibuffer window} (@pxref{Minibuffer Windows}).  Since the
+minibuffer window is used for displaying text, it has a body but it does
+not have a tab or header line or any margins.  Finally, a @dfn{tooltip
+window} which is used for displaying a tooltip in a tooltip frame
+(@pxref{Tooltips}) has a body too but no decorations at all.
 
-The selected window is considered part of a group when the buffer
-local variable @code{selected-window-group-function} is set to a
-function.  In this case, @code{selected-window-group} calls it with no
-arguments and returns its result (which should be the list of windows
-in the group).
-@end defun
 
 @node Windows and Frames
 @section Windows and Frames
 
-Each window belongs to exactly one frame (@pxref{Frames}).
+Each window belongs to exactly one frame (@pxref{Frames}).  For all
+windows belonging to a specific frame, we sometimes also say that these
+windows are @dfn{owned} by that frame or simply that they are on that frame.
 
 @defun window-frame &optional window
-This function returns the frame that the window @var{window} belongs
-to.  If @var{window} is @code{nil}, it defaults to the selected
-window.
+This function returns the specified @var{window}'s frame---the frame
+that @var{window} belongs to.  If @var{window} is omitted or @code{nil},
+it defaults to the selected window (@pxref{Selecting Windows}).
 @end defun
 
 @defun window-list &optional frame minibuffer window
-This function returns a list of live windows belonging to the frame
+This function returns a list of all live windows owned by the specified
 @var{frame}.  If @var{frame} is omitted or @code{nil}, it defaults to
-the selected frame.
+the selected frame (@pxref{Input Focus}).
 
-The optional argument @var{minibuffer} specifies whether to include
-the minibuffer window in the returned list.  If @var{minibuffer} is
-@code{t}, the minibuffer window is included.  If @var{minibuffer} is
+The optional argument @var{minibuffer} specifies whether to include the
+minibuffer window (@pxref{Minibuffer Windows}) in that list.  If
+@var{minibuffer} is @code{t}, the minibuffer window is included.  If
 @code{nil} or omitted, the minibuffer window is included only if it is
 active.  If @var{minibuffer} is neither @code{nil} nor @code{t}, the
 minibuffer window is never included.
 
-The optional argument @var{window}, if non-@code{nil}, should be a live
+Note that the window returned by @code{minibuffer-window} called with
+the argument @var{frame} is returned by @code{window-list} called with
+the same argument if and only if that window actually belongs to
+@var{frame}.  If the minibuffer window is owned by another frame, it is
+not returned by this invocation.
+
+The optional argument @var{window}, if non-@code{nil}, must be a live
 window on the specified frame; then @var{window} will be the first
 element in the returned list.  If @var{window} is omitted or @code{nil},
-the window selected within the frame is the first element.
+the window selected within @var{frame} (@pxref{Selecting Windows}) is
+the first element.
 @end defun
 
 @cindex window tree
 @cindex root window
-  Windows in the same frame are organized into a @dfn{window tree},
+  Windows on the same frame are organized into a @dfn{window tree},
 whose leaf nodes are the live windows.  The internal nodes of a window
 tree are not live; they exist for the purpose of organizing the
 relationships between live windows.  The root node of a window tree is
-called the @dfn{root window}.  It can be either a live window (if the
-frame has just one window), or an internal window.
-
-  A minibuffer window (@pxref{Minibuffer Windows}) that is not alone
-on its frame does not have a parent window, so it strictly speaking is
-not part of its frame's window tree.  Nonetheless, it is a sibling
-window of the frame's root window, and thus can be reached via
-@code{window-next-sibling}.  Also, the function @code{window-tree}
-described at the end of this section lists the minibuffer window
-alongside the actual window tree.
+called the @dfn{root window}.  It is either a live window or an
+internal window.  If it is a live window, then the frame has just one
+window besides the minibuffer window, or the frame is a
+minibuffer-only frame, @pxref{Frame Layout}.
+
+  A minibuffer window (@pxref{Minibuffer Windows}) that is not alone on
+its frame does not have a parent window, so it strictly speaking is not
+part of its frame's window tree.  Nonetheless, it is a sibling window of
+the frame's root window, and thus can be reached from the root window via
+@code{window-next-sibling}, see below.  Also, the function
+@code{window-tree} described at the end of this section lists the
+minibuffer window alongside the actual window tree.
 
 @defun frame-root-window &optional frame-or-window
 This function returns the root window for @var{frame-or-window}.  The
@@ -217,15 +276,15 @@ of that window's frame.
 @cindex parent window
 @cindex child window
 @cindex sibling window
-  When a window is split, there are two live windows where previously
-there was one.  One of these is represented by the same Lisp window
-object as the original window, and the other is represented by a
-newly-created Lisp window object.  Both of these live windows become
-leaf nodes of the window tree, as @dfn{child windows} of a single
-internal window.  If necessary, Emacs automatically creates this
-internal window, which is also called the @dfn{parent window}, and
-assigns it to the appropriate position in the window tree.  A set of
-windows that share the same parent are called @dfn{siblings}.
+  When a live window is split (@pxref{Splitting Windows}), there are two
+live windows where previously there was one.  One of these is
+represented by the same Lisp window object as the original window, and
+the other is represented by a newly-created Lisp window object.  Both of
+these live windows become leaf nodes of the window tree, as @dfn{child
+windows} of a single internal window.  If necessary, Emacs automatically
+creates this internal window, which is also called the @dfn{parent
+window}, and assigns it to the appropriate position in the window tree.
+The set of windows that share the same parent are called @dfn{siblings}.
 
 @cindex parent window
 @defun window-parent &optional window
@@ -235,16 +294,16 @@ window.  The return value is @code{nil} if @var{window} 
has no parent
 (i.e., it is a minibuffer window or the root window of its frame).
 @end defun
 
-  Each internal window always has at least two child windows.  If this
-number falls to one as a result of window deletion, Emacs
-automatically deletes the internal window, and its sole remaining
-child window takes its place in the window tree.
+  A parent window always has at least two child windows.  If this number
+were to fall to one as a result of window deletion (@pxref{Deleting
+Windows}), Emacs automatically deletes the parent window too, and its
+sole remaining child window takes its place in the window tree.
 
-  Each child window can be either a live window, or an internal window
+  A child window can be either a live window, or an internal window
 (which in turn would have its own child windows).  Therefore, each
 internal window can be thought of as occupying a certain rectangular
-@dfn{screen area}---the union of the areas occupied by the live
-windows that are ultimately descended from it.
+@dfn{screen area}---the union of the areas occupied by the live windows
+that are ultimately descended from it.
 
 @cindex window combination
 @cindex vertical combination
@@ -284,7 +343,9 @@ windows @var{W4} and @var{W5}.  Hence, the live windows in 
this
 window tree are @var{W2}, @var{W4}, and @var{W5}.
 
   The following functions can be used to retrieve a child window of an
-internal window, and the siblings of a child window.
+internal window, and the siblings of a child window.  Their @var{window}
+argument always defaults to the selected window (@pxref{Selecting
+Windows}).
 
 @defun window-top-child &optional window
 This function returns the topmost child window of @var{window}, if
@@ -309,8 +370,7 @@ the leftmost child window for a horizontal combination.  If
 
 @defun window-combined-p &optional window horizontal
 This function returns a non-@code{nil} value if and only if
-@var{window} is part of a vertical combination.  If @var{window} is
-omitted or @code{nil}, it defaults to the selected one.
+@var{window} is part of a vertical combination.
 
 If the optional argument @var{horizontal} is non-@code{nil}, this
 means to return non-@code{nil} if and only if @var{window} is part of
@@ -318,24 +378,21 @@ a horizontal combination.
 @end defun
 
 @defun window-next-sibling &optional window
-This function returns the next sibling of the window @var{window}.  If
-omitted or @code{nil}, @var{window} defaults to the selected window.
-The return value is @code{nil} if @var{window} is the last child of
-its parent.
+This function returns the next sibling of the specified @var{window}.  The
+return value is @code{nil} if @var{window} is the last child of its
+parent.
 @end defun
 
 @defun window-prev-sibling &optional window
-This function returns the previous sibling of the window @var{window}.
-If omitted or @code{nil}, @var{window} defaults to the selected
-window.  The return value is @code{nil} if @var{window} is the first
-child of its parent.
+This function returns the previous sibling of the specified @var{window}.
+The return value is @code{nil} if @var{window} is the first child of its
+parent.
 @end defun
 
-The functions @code{window-next-sibling} and
-@code{window-prev-sibling} should not be confused with the functions
-@code{next-window} and @code{previous-window}, which return the next
-and previous window, respectively, in the cyclic ordering of windows
-(@pxref{Cyclic Window Ordering}).
+The functions @code{window-next-sibling} and @code{window-prev-sibling}
+should not be confused with the functions @code{next-window} and
+@code{previous-window}, which return the next and previous window in the
+cyclic ordering of windows (@pxref{Cyclic Window Ordering}).
 
   The following functions can be useful to locate a window within its
 frame.
@@ -408,8 +465,7 @@ Don't use this function to check whether there is @emph{no} 
window in
 much more efficient way to do that.
 @end defun
 
-The following function allows the entire window tree of a frame to be
-retrieved:
+The following function retrieves the entire window tree of a frame:
 
 @defun window-tree &optional frame
 This function returns a list representing the window tree for frame
@@ -433,54 +489,218 @@ internal window).  The @var{edges} element is a list 
@code{(@var{left}
 @end defun
 
 
-@node Window Sizes
-@section Window Sizes
-@cindex window size
-@cindex size of window
+@node Selecting Windows
+@section Selecting Windows
+@cindex selecting a window
 
-  The following schematic shows the structure of a live window:
+@cindex selected window
+@cindex window selected within a frame
+  In each frame, at any time, exactly one Emacs window is designated
+as @dfn{selected within the frame}.  For the selected frame, that
+window is called the @dfn{selected window}---the one in which most
+editing takes place, and in which the cursor for selected windows
+appears (@pxref{Cursor Parameters}).  Keyboard input that inserts or
+deletes text is also normally directed to this window.   The selected
+window's buffer is usually also the current buffer, except when
+@code{set-buffer} has been used (@pxref{Current Buffer}).  As for
+non-selected frames, the window selected within the frame becomes the
+selected window if the frame is ever selected.
 
-@smallexample
-@group
-        ____________________________________________
-       |______________ Header Line ______________|RD| ^
-     ^ |LS|LM|LF|                       |RF|RM|RS|  | |
-     | |  |  |  |                       |  |  |  |  | |
-Window |  |  |  |       Text Area       |  |  |  |  | Window
-Body | |  |  |  |     (Window Body)     |  |  |  |  | Total
-Height |  |  |  |                       |  |  |  |  | Height
-     | |  |  |  |<- Window Body Width ->|  |  |  |  | |
-     v |__|__|__|_______________________|__|__|__|  | |
-       |_________ Horizontal Scroll Bar _________|  | |
-       |_______________ Mode Line _______________|__| |
-       |_____________ Bottom Divider _______________| v
-        <---------- Window Total Width ------------>
+@defun selected-window
+This function returns the selected window (which is always a live
+window).
+@end defun
 
-@end group
-@end smallexample
+The following function explicitly selects a window and its frame.
 
-@cindex window body
-@cindex text area of a window
-@cindex body of a window
-  At the center of the window is the @dfn{text area}, or @dfn{body},
-where the buffer text is displayed.  The text area can be surrounded by
-a series of optional areas.  On the left and right, from innermost to
-outermost, these are the left and right fringes, denoted by LF and RF
-(@pxref{Fringes}); the left and right margins, denoted by LM and RM in
-the schematic (@pxref{Display Margins}); the left or right vertical
-scroll bar, only one of which is present at any time, denoted by LS and
-RS (@pxref{Scroll Bars}); and the right divider, denoted by RD
-(@pxref{Window Dividers}).  At the top of the window is the header line
-(@pxref{Header Lines}).  At the bottom of the window are the horizontal
-scroll bar (@pxref{Scroll Bars}); the mode line (@pxref{Mode Line
-Format}); and the bottom divider (@pxref{Window Dividers}).
+@defun select-window window &optional norecord
+This function makes @var{window} the selected window and the window
+selected within its frame, and selects that frame.  It also makes
+@var{window}'s buffer (@pxref{Buffers and Windows}) current and sets
+that buffer's value of @code{point} to the value of @code{window-point}
+(@pxref{Window Point}) in @var{window}.  @var{window} must be a live
+window.  The return value is @var{window}.
+
+By default, this function also moves @var{window}'s buffer to the front
+of the buffer list (@pxref{Buffer List}) and makes @var{window} the most
+recently selected window.  If the optional argument @var{norecord} is
+non-@code{nil}, these additional actions are omitted.
+
+In addition, this function by default also tells the display engine to
+update the display of @var{window} when its frame gets redisplayed the
+next time.  If @var{norecord} is non-@code{nil}, such updates are
+usually not performed.  If, however, @var{norecord} equals the special
+symbol @code{mark-for-redisplay}, the additional actions mentioned above
+are omitted but @var{window}'s display will be nevertheless updated.
 
-  Emacs provides miscellaneous functions for finding the height and
-width of a window.  The return value of many of these functions can be
+Note that sometimes selecting a window is not enough to show it, or
+make its frame the top-most frame on display: you may also need to
+raise the frame or make sure input focus is directed to that frame.
+@xref{Input Focus}.
+@end defun
+
+@cindex select window hooks
+@cindex running a hook when a window gets selected
+For historical reasons, Emacs does not run a separate hook whenever a
+window gets selected.  Applications and internal routines often
+temporarily select a window to perform a few actions on it.  They do
+that either to simplify coding---because many functions by default
+operate on the selected window when no @var{window} argument is
+specified---or because some functions did not (and still do not) take a
+window as argument and always operate(d) on the selected window instead.
+Running a hook every time a window gets selected for a short time and
+once more when the previously selected window gets restored is not
+useful.
+
+  However, when its @var{norecord} argument is @code{nil},
+@code{select-window} updates the buffer list and thus indirectly runs
+the normal hook @code{buffer-list-update-hook} (@pxref{Buffer List}).
+Consequently, that hook provides one way to run a function whenever a
+window gets selected more ``permanently''.
+
+  Since @code{buffer-list-update-hook} is also run by functions that are
+not related to window management, it will usually make sense to save the
+value of the selected window somewhere and compare it with the value of
+@code{selected-window} while running that hook.  Also, to avoid false
+positives when using @code{buffer-list-update-hook}, it is good practice
+that every @code{select-window} call supposed to select a window only
+temporarily passes a non-@code{nil} @var{norecord} argument.  If
+possible, the macro @code{with-selected-window} (see below) should be
+used in such cases.
+
+  Emacs also runs the hook @code{window-selection-change-functions}
+whenever the redisplay routine detects that another window has been
+selected since last redisplay.  @xref{Window Hooks}, for a detailed
+explanation.  @code{window-state-change-functions} (described in the
+same section) is another abnormal hook run after a different window
+has been selected but is triggered by other window changes as well.
+
+@cindex most recently selected windows
+  The sequence of calls to @code{select-window} with a non-@code{nil}
+@var{norecord} argument determines an ordering of windows by their
+selection or use time, see below.  The function @code{get-lru-window},
+for example, can then be used to retrieve the least recently selected
+window (@pxref{Cyclic Window Ordering}).
+
+@defun frame-selected-window &optional frame
+This function returns the window on @var{frame} that is selected
+within that frame.  @var{frame} should be a live frame; if omitted or
+@code{nil}, it defaults to the selected frame.
+@end defun
+
+@defun set-frame-selected-window frame window &optional norecord
+This function makes @var{window} the window selected within the frame
+@var{frame}.  @var{frame} should be a live frame; if @code{nil}, it
+defaults to the selected frame.  @var{window} should be a live window;
+if @code{nil}, it defaults to the selected window.
+
+If @var{frame} is the selected frame, this makes @var{window} the
+selected window.
+
+If the optional argument @var{norecord} is non-@code{nil}, this function
+does not alter the ordering of the most recently selected windows, nor
+the buffer list.
+@end defun
+
+  The following macros are useful to temporarily select a window without
+affecting the ordering of recently selected windows or the buffer list.
+
+@defmac save-selected-window forms@dots{}
+This macro records the selected frame, as well as the selected window
+of each frame, executes @var{forms} in sequence, then restores the
+earlier selected frame and windows.  It also saves and restores the
+current buffer.  It returns the value of the last form in @var{forms}.
+
+This macro does not save or restore anything about the sizes,
+arrangement or contents of windows; therefore, if @var{forms} change
+them, the change persists.  If the previously selected window of some
+frame is no longer live at the time of exit from @var{forms}, that
+frame's selected window is left alone.  If the previously selected
+window is no longer live, then whatever window is selected at the end of
+@var{forms} remains selected.  The current buffer is restored if and
+only if it is still live when exiting @var{forms}.
+
+This macro changes neither the ordering of recently selected windows nor
+the buffer list.
+@end defmac
+
+@defmac with-selected-window window forms@dots{}
+This macro selects @var{window}, executes @var{forms} in sequence, then
+restores the previously selected window and current buffer.  The
+ordering of recently selected windows and the buffer list remain
+unchanged unless you deliberately change them within @var{forms}; for
+example, by calling @code{select-window} with argument @var{norecord}
+@code{nil}.  Hence, this macro is the preferred way to temporarily work
+with @var{window} as the selected window without needlessly running
+@code{buffer-list-update-hook}.
+@end defmac
+
+@defmac with-selected-frame frame forms@dots{}
+This macro executes @var{forms} with @var{frame} as the selected
+frame.  The value returned is the value of the last form in
+@var{forms}.  This macro saves and restores the selected frame, and
+changes the order of neither the recently selected windows nor the
+buffers in the buffer list.
+@end defmac
+
+@cindex window use time
+@cindex use time of window
+@cindex window order by time of last use
+@defun window-use-time &optional window
+This function returns the use time of window @var{window}.  @var{window}
+must be a live window and defaults to the selected one.
+
+The @dfn{use time} of a window is not really a time value, but an
+integer that does increase monotonically with each call of
+@code{select-window} with a @code{nil} @var{norecord} argument.  The
+window with the lowest use time is usually called the least recently
+used window while the window with the highest use time is called the
+most recently used one (@pxref{Cyclic Window Ordering}).
+@end defun
+
+@defun window-bump-use-time &optional window
+This function marks @var{window} as being the most recently used
+one.  This can be useful when writing certain @code{pop-to-buffer}
+scenarios (@pxref{Switching Buffers}).  @var{window} must be a live
+window and defaults to the selected one.
+@end defun
+
+@anchor{Window Group}Sometimes several windows collectively and
+cooperatively display a buffer, for example, under the management of
+Follow Mode (@pxref{Follow Mode,,, emacs}), where the windows together
+display a bigger portion of the buffer than one window could alone.
+It is often useful to consider such a @dfn{window group} as a single
+entity.  Several functions such as @code{window-group-start}
+(@pxref{Window Start and End}) allow you to do this by supplying, as
+an argument, one of the windows as a stand-in for the whole group.
+
+@defun selected-window-group
+@vindex selected-window-group-function
+When the selected window is a member of a group of windows, this
+function returns a list of the windows in the group, ordered such that
+the first window in the list is displaying the earliest part of the
+buffer, and so on.  Otherwise the function returns a list containing
+just the selected window.
+
+The selected window is considered part of a group when the buffer
+local variable @code{selected-window-group-function} is set to a
+function.  In this case, @code{selected-window-group} calls it with no
+arguments and returns its result (which should be the list of windows
+in the group).
+@end defun
+
+
+@node Window Sizes
+@section Window Sizes
+@cindex window size
+@cindex size of window
+
+Emacs provides miscellaneous functions for finding the height and width
+of a window.  The return value of many of these functions can be
 specified either in units of pixels or in units of lines and columns.
 On a graphical display, the latter actually correspond to the height and
-width of a default character specified by the frame's default font
-as returned by @code{frame-char-height} and @code{frame-char-width}
+width of a default character specified by the frame's default font as
+returned by @code{frame-char-height} and @code{frame-char-width}
 (@pxref{Frame Font}).  Thus, if a window is displaying text with a
 different font or size, the reported line height and column width for
 that window may differ from the actual number of text lines or columns
@@ -490,8 +710,7 @@ displayed within it.
 @cindex height of a window
 @cindex total height of a window
   The @dfn{total height} of a window is the number of lines comprising
-the window's body, the header line, the horizontal scroll bar, the mode
-line and the bottom divider (if any).
+its body and its top and bottom decorations (@pxref{Basic Windows}).
 
 @defun window-total-height &optional window round
 This function returns the total height, in lines, of the window
@@ -521,9 +740,8 @@ with any other @var{round} it returns the internal value of
 @cindex window width
 @cindex width of a window
 @cindex total width of a window
-The @dfn{total width} of a window is the number of lines comprising the
-window's body, its margins, fringes, scroll bars and a right divider (if
-any).
+The @dfn{total width} of a window is the number of lines comprising its
+body and its left and right decorations (@pxref{Basic Windows}).
 
 @defun window-total-width &optional window round
 This function returns the total width, in columns, of the window
@@ -564,10 +782,9 @@ window in units of pixels.
 This function returns the total height of window @var{window} in pixels.
 @var{window} must be a valid window and defaults to the selected one.
 
-The return value includes mode and header line, a horizontal scroll bar
-and a bottom divider, if any.  If @var{window} is an internal window,
-its pixel height is the pixel height of the screen areas spanned by its
-children.
+The return value includes the heights of @var{window}'s top and bottom
+decorations.  If @var{window} is an internal window, its pixel height is
+the pixel height of the screen areas spanned by its children.
 @end defun
 
 @cindex window pixel width
@@ -578,10 +795,9 @@ children.
 This function returns the width of window @var{window} in pixels.
 @var{window} must be a valid window and defaults to the selected one.
 
-The return value includes the fringes and margins of @var{window} as
-well as any vertical dividers or scroll bars belonging to @var{window}.
-If @var{window} is an internal window, its pixel width is the width of
-the screen areas spanned by its children.
+The return value includes the widths of @var{window}'s left and right
+decorations.  If @var{window} is an internal window, its pixel width is
+the width of the screen areas spanned by its children.
 @end defun
 
 @cindex full-width window
@@ -608,8 +824,8 @@ that of the root window on that frame.  If @var{window} is 
omitted or
 @cindex window body height
 @cindex body height of a window
 The @dfn{body height} of a window is the height of its text area, which
-does not include a mode or header line, a horizontal scroll bar, or a
-bottom divider.
+does not include any of its top or bottom decorations (@pxref{Basic
+Windows}).
 
 @defun window-body-height &optional window pixelwise
 This function returns the height, in lines, of the body of window
@@ -629,7 +845,9 @@ exceed its total height as returned by 
@code{window-total-height}.
 @cindex window body width
 @cindex body width of a window
 The @dfn{body width} of a window is the width of its text area, which
-does not include the scroll bar, fringes, margins or a right divider.
+does not include any of its left or right decorations (@pxref{Basic
+Windows}).
+
 Note that when one or both fringes are removed (by setting their width
 to zero), the display engine reserves two character cells, one on each
 side of the window, for displaying the continuation and truncation
@@ -662,16 +880,11 @@ to calling @code{window-body-width}.  In either case, the 
optional
 argument @var{pixelwise} is passed to the function called.
 @end defun
 
-For compatibility with previous versions of Emacs,
-@code{window-height} is an alias for @code{window-total-height}, and
-@code{window-width} is an alias for @code{window-body-width}.  These
-aliases are considered obsolete and will be removed in the future.
-
-   The pixel heights of a window's mode and header line can be retrieved
-with the functions given below.  Their return value is usually accurate
-unless the window has not been displayed before: In that case, the
-return value is based on an estimate of the font used for the window's
-frame.
+   The pixel heights of a window's mode, tab and header line can be
+retrieved with the functions given below.  Their return value is usually
+accurate unless the window has not been displayed before: In that case,
+the return value is based on an estimate of the font used for the
+window's frame.
 
 @defun window-mode-line-height &optional window
 This function returns the height in pixels of @var{window}'s mode line.
@@ -679,6 +892,12 @@ This function returns the height in pixels of 
@var{window}'s mode line.
 @var{window} has no mode line, the return value is zero.
 @end defun
 
+@defun window-tab-line-height &optional window
+This function returns the height in pixels of @var{window}'s tab line.
+@var{window} must be a live window and defaults to the selected one.  If
+@var{window} has no tab line, the return value is zero.
+@end defun
+
 @defun window-header-line-height &optional window
 This function returns the height in pixels of @var{window}'s header
 line.  @var{window} must be a live window and defaults to the selected
@@ -720,15 +939,14 @@ size (@pxref{Preserving Window Sizes}).
 
 @defopt window-min-height
 This option specifies the minimum total height, in lines, of any window.
-Its value has to accommodate at least one text line as well as a mode
-and header line, a horizontal scroll bar and a bottom divider, if
-present.
+Its value has to accommodate at least one text line and any top or
+bottom decorations.
 @end defopt
 
 @defopt window-min-width
 This option specifies the minimum total width, in columns, of any
-window.  Its value has to accommodate two text columns as well as
-margins, fringes, a scroll bar and a right divider, if present.
+window.  Its value has to accommodate at least two text columns and any
+left or right decorations.
 @end defopt
 
 The following function tells how small a specific window can get taking
@@ -745,10 +963,9 @@ of @var{window}'s lines.
 
 The return value makes sure that all components of @var{window} remain
 fully visible if @var{window}'s size were actually set to it.  With
-@var{horizontal} @code{nil} it includes the mode and header line, the
-horizontal scroll bar and the bottom divider, if present.  With
-@var{horizontal} non-@code{nil} it includes the margins and fringes, the
-vertical scroll bar and the right divider, if present.
+@var{horizontal} @code{nil} it includes any top or bottom decorations.
+With @var{horizontal} non-@code{nil} it includes any left or right
+decorations of @var{window}.
 
 The optional argument @var{ignore}, if non-@code{nil}, means ignore
 restrictions imposed by fixed size windows, @code{window-min-height} or
@@ -770,10 +987,10 @@ minimum size of @var{window} counted in pixels.
 @cindex changing window size
 @cindex window size, changing
 
-  This section describes functions for resizing a window without
-changing the size of its frame.  Because live windows do not overlap,
-these functions are meaningful only on frames that contain two or more
-windows: resizing a window also changes the size of a neighboring
+This section describes functions for resizing a window without changing
+the size of its frame.  Because live windows do not overlap, these
+functions are meaningful only on frames that contain two or more
+windows: resizing a window also changes the size of at least one other
 window.  If there is just one window on a frame, its size cannot be
 changed except by resizing the frame (@pxref{Frame Size}).
 
@@ -801,11 +1018,10 @@ Normally, the variables @code{window-min-height} and
 (@pxref{Window Sizes}).  However, if the optional argument @var{ignore}
 is non-@code{nil}, this function ignores @code{window-min-height} and
 @code{window-min-width}, as well as @code{window-size-fixed}.  Instead,
-it considers the minimum-height window to be one consisting of a header
-and a mode line, a horizontal scrollbar and a bottom divider (if any),
-plus a text area one line tall; and a minimum-width window as one
-consisting of fringes, margins, a scroll bar and a right divider (if
-any), plus a text area two columns wide.
+it considers the minimum height of a window as the sum of its top and
+bottom decorations plus a text area of one line; and its minimum width
+as the sum of its left and right decorations plus a text area of two
+columns.
 
 If the optional argument @var{pixelwise} is non-@code{nil},
 @var{delta} is interpreted as pixels.
@@ -889,7 +1105,7 @@ that this function can give @var{window}.  The optional 
argument
 @var{min-height}, if non-@code{nil}, specifies the minimum total height
 that it can give, which overrides the variable @code{window-min-height}.
 Both @var{max-height} and @var{min-height} are specified in lines and
-include mode and header line and a bottom divider, if any.
+include any top or bottom decorations of @var{window}.
 
 If @var{window} is part of a horizontal combination and the value of the
 option @code{fit-window-to-buffer-horizontally} (see below) is
@@ -900,8 +1116,8 @@ The optional argument @var{max-width} specifies a maximum 
width and
 defaults to the width of @var{window}'s frame.  The optional argument
 @var{min-width} specifies a minimum width and defaults to
 @code{window-min-width}.  Both @var{max-width} and @var{min-width} are
-specified in columns and include fringes, margins and scrollbars, if
-any.
+specified in columns and include any left or right decorations of
+@var{window}.
 
 The optional argument @var{preserve-size}, if non-@code{nil}, will
 install a parameter to preserve the size of @var{window} during future
@@ -1148,15 +1364,14 @@ one that has space for a text area one line tall and/or 
two columns
 wide.
 
 Hence, if @var{size} is specified, it's the caller's responsibility to
-check whether the emanating windows are large enough to encompass all
-areas like a mode line or a scroll bar.  The function
+check whether the emanating windows are large enough to encompass all of
+their decorations like a mode line or a scroll bar.  The function
 @code{window-min-size} (@pxref{Window Sizes}) can be used to determine
 the minimum requirements of @var{window} in this regard.  Since the new
-window usually inherits areas like the mode line or the scroll bar
-from @var{window}, that function is also a good guess for the minimum
-size of the new window.  The caller should specify a smaller size only
-if it correspondingly removes an inherited area before the next
-redisplay.
+window usually inherits areas like the mode line or the scroll bar from
+@var{window}, that function is also a good guess for the minimum size of
+the new window.  The caller should specify a smaller size only if it
+correspondingly removes an inherited area before the next redisplay.
 
 The optional third argument @var{side} determines the position of the
 new window relative to @var{window}.  If it is @code{nil} or
@@ -1762,153 +1977,6 @@ distribute its space proportionally among the two 
remaining live
 windows.
 
 
-@node Selecting Windows
-@section Selecting Windows
-@cindex selecting a window
-
-@defun select-window window &optional norecord
-This function makes @var{window} the selected window and the window
-selected within its frame (@pxref{Basic Windows}), and selects that
-frame.  It also makes @var{window}'s buffer (@pxref{Buffers and
-Windows}) current and sets that buffer's value of @code{point} to the
-value of @code{window-point} (@pxref{Window Point}) in @var{window}.
-@var{window} must be a live window.  The return value is @var{window}.
-
-By default, this function also moves @var{window}'s buffer to the front
-of the buffer list (@pxref{Buffer List}) and makes @var{window} the most
-recently selected window.  If the optional argument @var{norecord} is
-non-@code{nil}, these additional actions are omitted.
-
-In addition, this function by default also tells the display engine to
-update the display of @var{window} when its frame gets redisplayed the
-next time.  If @var{norecord} is non-@code{nil}, such updates are
-usually not performed.  If, however, @var{norecord} equals the special
-symbol @code{mark-for-redisplay}, the additional actions mentioned above
-are omitted but @var{window} will be nevertheless updated.
-
-Note that sometimes selecting a window is not enough to show it, or
-make its frame the top-most frame on display: you may also need to
-raise the frame or make sure input focus is directed to that frame.
-@xref{Input Focus}.
-@end defun
-
-@cindex select window hooks
-@cindex running a hook when a window gets selected
-For historical reasons, Emacs does not run a separate hook whenever a
-window gets selected.  Applications and internal routines often
-temporarily select a window to perform a few actions on it.  They do
-that either to simplify coding---because many functions by default
-operate on the selected window when no @var{window} argument is
-specified---or because some functions did not (and still do not) take a
-window as argument and always operate(d) on the selected window instead.
-Running a hook every time a window gets selected for a short time and
-once more when the previously selected window gets restored is not
-useful.
-
-  However, when its @var{norecord} argument is @code{nil},
-@code{select-window} updates the buffer list and thus indirectly runs
-the normal hook @code{buffer-list-update-hook} (@pxref{Buffer List}).
-Consequently, that hook provides one way to run a function whenever a
-window gets selected more ``permanently''.
-
-  Since @code{buffer-list-update-hook} is also run by functions that are
-not related to window management, it will usually make sense to save the
-value of the selected window somewhere and compare it with the value of
-@code{selected-window} while running that hook.  Also, to avoid false
-positives when using @code{buffer-list-update-hook}, it is good practice
-that every @code{select-window} call supposed to select a window only
-temporarily passes a non-@code{nil} @var{norecord} argument.  If
-possible, the macro @code{with-selected-window} (see below) should be
-used in such cases.
-
-  Emacs also runs the hook @code{window-selection-change-functions}
-whenever the redisplay routine detects that another window has been
-selected since last redisplay.  @xref{Window Hooks}, for a detailed
-explanation.  @code{window-state-change-functions} (described in the
-same section) is another abnormal hook run after a different window
-has been selected but is triggered by other window changes as well.
-
-@cindex most recently selected windows
-  The sequence of calls to @code{select-window} with a non-@code{nil}
-@var{norecord} argument determines an ordering of windows by their
-selection time.  The function @code{get-lru-window} can be used to
-retrieve the least recently selected live window (@pxref{Cyclic Window
-Ordering}).
-
-@defmac save-selected-window forms@dots{}
-This macro records the selected frame, as well as the selected window
-of each frame, executes @var{forms} in sequence, then restores the
-earlier selected frame and windows.  It also saves and restores the
-current buffer.  It returns the value of the last form in @var{forms}.
-
-This macro does not save or restore anything about the sizes,
-arrangement or contents of windows; therefore, if @var{forms} change
-them, the change persists.  If the previously selected window of some
-frame is no longer live at the time of exit from @var{forms}, that
-frame's selected window is left alone.  If the previously selected
-window is no longer live, then whatever window is selected at the end of
-@var{forms} remains selected.  The current buffer is restored if and
-only if it is still live when exiting @var{forms}.
-
-This macro changes neither the ordering of recently selected windows nor
-the buffer list.
-@end defmac
-
-@defmac with-selected-window window forms@dots{}
-This macro selects @var{window}, executes @var{forms} in sequence, then
-restores the previously selected window and current buffer.  The
-ordering of recently selected windows and the buffer list remain
-unchanged unless you deliberately change them within @var{forms}; for
-example, by calling @code{select-window} with argument @var{norecord}
-@code{nil}.  Hence, this macro is the preferred way to temporarily work
-with @var{window} as the selected window without needlessly running
-@code{buffer-list-update-hook}.
-@end defmac
-
-@defmac with-selected-frame frame forms@dots{}
-This macro executes @var{forms} with @var{frame} as the selected
-frame.  The value returned is the value of the last form in
-@var{forms}.  This macro saves and restores the selected frame, and
-changes the order of neither the recently selected windows nor the
-buffers in the buffer list.
-@end defmac
-
-@defun frame-selected-window &optional frame
-This function returns the window on @var{frame} that is selected
-within that frame.  @var{frame} should be a live frame; if omitted or
-@code{nil}, it defaults to the selected frame.
-@end defun
-
-@defun set-frame-selected-window frame window &optional norecord
-This function makes @var{window} the window selected within the frame
-@var{frame}.  @var{frame} should be a live frame; if @code{nil}, it
-defaults to the selected frame.  @var{window} should be a live window;
-if @code{nil}, it defaults to the selected window.
-
-If @var{frame} is the selected frame, this makes @var{window} the
-selected window.
-
-If the optional argument @var{norecord} is non-@code{nil}, this
-function does not alter the list of most recently selected windows,
-nor the buffer list.
-@end defun
-
-@cindex window use time
-@cindex use time of window
-@cindex window order by time of last use
-@defun window-use-time &optional window
-This functions returns the use time of window @var{window}.
-@var{window} must be a live window and defaults to the selected one.
-
-The @dfn{use time} of a window is not really a time value, but an
-integer that does increase monotonically with each call of
-@code{select-window} with a @code{nil} @var{norecord} argument.  The
-window with the lowest use time is usually called the least recently
-used window while the window with the highest use time is called the
-most recently used one (@pxref{Cyclic Window Ordering}).
-@end defun
-
-
 @node Cyclic Window Ordering
 @section Cyclic Ordering of Windows
 @cindex cyclic ordering of windows
@@ -2036,8 +2104,11 @@ criterion, without selecting it:
 @cindex least recently used window
 @defun get-lru-window &optional all-frames dedicated not-selected no-other
 This function returns a live window which is heuristically the least
-recently used.  The optional argument @var{all-frames} has
-the same meaning as in @code{next-window}.
+recently used one.  The @dfn{least recently used window} is the least
+recently selected one---the window whose use time is less than the use
+time of all other live windows (@pxref{Selecting Windows}).  The
+optional argument @var{all-frames} has the same meaning as in
+@code{next-window}.
 
 If any full-width windows are present, only those windows are
 considered.  A minibuffer window is never a candidate.  A dedicated
@@ -2053,8 +2124,14 @@ function returns @code{nil} in that case.  The optional 
argument
 @cindex most recently used window
 @defun get-mru-window &optional all-frames dedicated not-selected no-other
 This function is like @code{get-lru-window}, but it returns the most
-recently used window instead.  The meaning of the arguments is the
-same as for @code{get-lru-window}.
+recently used window instead.  The @dfn{most recently used window} is
+the most recently selected one---the window whose use time exceeds the
+use time of all other live windows (@pxref{Selecting Windows}).  The
+meaning of the arguments is the same as for @code{get-lru-window}.
+
+Since in practice the most recently used window is always the selected
+one, it usually makes sense to call this function with a non-@code{nil}
+@var{not-selected} argument only.
 @end defun
 
 @cindex largest window
@@ -2081,11 +2158,6 @@ windows to search, and have the same meanings as in
 @code{next-window}.
 @end defun
 
-@defun window-bump-use-time window
-This function marks @var{window} as having been recently used.  This
-can be useful when creating certain @code{pop-to-buffer} scenarios.
-@end defun
-
 
 @node Buffers and Windows
 @section Buffers and Windows
@@ -5611,10 +5683,9 @@ right of the rightmost column, and the Y coordinate one 
row down from
 the bottommost row.
 
 Note that these are the actual outer edges of the window, including any
-header line, mode line, scroll bar, fringes, window divider and display
-margins.  On a text terminal, if the window has a neighbor on its right,
-its right edge includes the separator line between the window and its
-neighbor.
+of its decorations.  On a text terminal, if the window has a neighbor on
+its right, its right edge includes the separator line between the window
+and its neighbor.
 
 If the optional argument @var{body} is @code{nil}, this means to
 return the edges corresponding to the total size of @var{window}.
@@ -5930,12 +6001,11 @@ all other child frames of that frame's parent frame.
 @cindex saving window information
 
 A @dfn{window configuration} records the entire layout of one
-frame---all windows, their sizes, which buffers they contain, how those
-buffers are scrolled, and their value of point; also their
-fringes, margins, and scroll bar settings.  It also includes the value
-of @code{minibuffer-scroll-window}.  As a special exception, the window
-configuration does not record the value of point in the selected window
-for the current buffer.
+frame---all windows, their sizes, their decorations, which buffers they
+contain, how those buffers are scrolled, and their value of point, It
+also includes the value of @code{minibuffer-scroll-window}.  As a
+special exception, the window configuration does not record the value of
+point in the selected window for the current buffer.
 
   You can bring back an entire frame layout by restoring a previously
 saved window configuration.  If you want to record the layout of all
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index e11267e..c77ccf7 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -2865,7 +2865,7 @@ that always equals one.  Let's try to verify this 
identity.
 @smallexample
 @group
 2:  -64        2:  -64        2:  -64        2:  9.7192e54  2:  9.7192e54
-1:  -64        1:  -3.1175e27 1:  9.7192e54  1:  -64        1:  9.7192e54
+1:  -64        1:  3.1175e27  1:  9.7192e54  1:  -64        1:  9.7192e54
     .              .              .              .              .
 
  64 n @key{RET} @key{RET}      H C            2 ^            @key{TAB}         
   H S 2 ^
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index cbb0d38..5e7813c 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -98,6 +98,15 @@ latest stable version of Org should be compatible with Emacs 
28.x,
 
 See [[https://orgmode.org/worg/org-maintenance.html#emacs-compatibility][this 
note on Worg]] and [[git::519947e508e081e71bf67db99e27b1c171ba4dfe][this 
commit]].
 
+*** The keybinding for ~org-table-blank-field~ has been removed
+
+If you prefer to keep the keybinding, you can add it back to
+~org-mode-map~ like so:
+
+#+begin_src emacs-lisp
+(define-key org-mode-map (kbd "C-c SPC") #'org-table-blank-field)
+#+end_src
+
 ** New features
 
 *** New citation engine
diff --git a/lisp/org/oc-basic.el b/lisp/org/oc-basic.el
index 98242f3..c51c7d3 100644
--- a/lisp/org/oc-basic.el
+++ b/lisp/org/oc-basic.el
@@ -69,7 +69,6 @@
 (require 'bibtex)
 (require 'json)
 (require 'oc)
-(require 'org)
 (require 'seq)
 
 (declare-function org-open-at-point "org" (&optional arg))
diff --git a/lisp/org/oc-biblatex.el b/lisp/org/oc-biblatex.el
index daf56e7..e985963 100644
--- a/lisp/org/oc-biblatex.el
+++ b/lisp/org/oc-biblatex.el
@@ -213,8 +213,8 @@ PROPS is the local properties of the bibliography, as a 
property list."
 
 (defun org-cite-biblatex-export-citation (citation style _ info)
   "Export CITATION object.
-STYLE is the citation style, as a string or nil.  INFO is the export state, as
-a property list."
+STYLE is the citation style, as a pair of either strings or nil.
+INFO is the export state, as a property list."
   (apply
    #'org-cite-biblatex--command citation info
    (pcase style
diff --git a/lisp/org/oc-csl.el b/lisp/org/oc-csl.el
index 3d13880..94de97e 100644
--- a/lisp/org/oc-csl.el
+++ b/lisp/org/oc-csl.el
@@ -248,11 +248,11 @@ If nil then the Chicago author-date style is used as a 
fallback.")
     ("paras."    . "paragraph")
     ("¶"         . "paragraph")
     ("¶¶"        . "paragraph")
-    ("§"         . "paragraph")
-    ("§§"        . "paragraph")
     ("part"      . "part")
     ("pt."       . "part")
     ("pts."      . "part")
+    ("§"         . "section")
+    ("§§"        . "section")
     ("section"   . "section")
     ("sec."      . "section")
     ("secs."     . "section")
@@ -270,11 +270,12 @@ If nil then the Chicago author-date style is used as a 
fallback.")
 (defconst org-cite-csl--label-regexp
   ;; Prior to Emacs-27.1 argument of `regexp' form must be a string literal.
   ;; It is the reason why `rx' is avoided here.
-  (rx-to-string `(seq word-start
-                      (regexp ,(regexp-opt (mapcar #'car 
org-cite-csl--label-alist) t))
-                      (0+ digit)
-                      (or word-start line-end (any ?\s ?\t)))
-                t)
+  (rx-to-string
+   `(seq (or line-start space)
+         (regexp ,(regexp-opt (mapcar #'car org-cite-csl--label-alist) t))
+         (0+ digit)
+         (or word-end line-end space " "))
+   t)
   "Regexp matching a label in a citation reference suffix.
 Label is in match group 1.")
 
@@ -371,7 +372,7 @@ or raise an error if the variable is unset."
     ((and (guard org-cite-csl-styles-dir) file)
      (expand-file-name file org-cite-csl-styles-dir))
     (other
-     (user-error "Cannot handle relative style file name" other))))
+     (user-error "Cannot handle relative style file name: %S" other))))
 
 (defun org-cite-csl--locale-getter ()
   "Return a locale getter.
@@ -425,7 +426,9 @@ The result is a association list.  Keys are: `id', 
`prefix',`suffix',
        ((re-search-forward org-cite-csl--label-regexp nil t)
         (setq location-start (match-beginning 0))
         (setq label (cdr (assoc (match-string 1) org-cite-csl--label-alist)))
-        (setq locator-start (match-end 1)))
+        (goto-char (match-end 1))
+        (skip-chars-forward "[:space:] ")
+        (setq locator-start (point)))
        ((re-search-forward (rx digit) nil t)
         (setq location-start (match-beginning 0))
         (setq label "page")
diff --git a/lisp/org/oc.el b/lisp/org/oc.el
index 2f74176..dcda8d7 100644
--- a/lisp/org/oc.el
+++ b/lisp/org/oc.el
@@ -789,6 +789,20 @@ Citations are ordered by appearance in the document, when 
following footnotes.
 INFO is the export communication channel, as a property list."
   (or (plist-get info :citations)
       (letrec ((cites nil)
+               (tree (plist-get info :parse-tree))
+               (find-definition
+                ;; Find definition for standard reference LABEL.  At
+                ;; this point, it is impossible to rely on
+                ;; `org-export-get-footnote-definition' because the
+                ;; function caches results that could contain
+                ;; un-processed citation objects.  So we use
+                ;; a simplified version of the function above.
+                (lambda (label)
+                  (org-element-map tree 'footnote-definition
+                    (lambda (d)
+                      (and (equal label (org-element-property :label d))
+                           (or (org-element-contents d) "")))
+                    info t)))
                (search-cites
                 (lambda (data)
                   (org-element-map data '(citation footnote-reference)
@@ -798,22 +812,13 @@ INFO is the export communication channel, as a property 
list."
                        ;; Do not force entering inline definitions, since
                        ;; `org-element-map' is going to enter it anyway.
                         ((guard (eq 'inline (org-element-property :type 
datum))))
-                        ;; Find definition for current standard
-                        ;; footnote reference.  Unlike to
-                        ;; `org-export-get-footnote-definition', do
-                        ;; not cache results as they would contain
-                        ;; un-processed citation objects.
+                        ;; Walk footnote definition.
                         (_
                          (let ((label (org-element-property :label datum)))
-                           (funcall
-                            search-cites
-                            (org-element-map data 'footnote-definition
-                              (lambda (d)
-                                (and
-                                 (equal label (org-element-property :label d))
-                                 (or (org-element-contents d) "")))))))))
+                           (funcall search-cites
+                                    (funcall find-definition label))))))
                     info nil 'footnote-definition t))))
-        (funcall search-cites (plist-get info :parse-tree))
+        (funcall search-cites tree)
         (let ((result (nreverse cites)))
           (plist-put info :citations result)
           result))))
@@ -1593,8 +1598,9 @@ The generated function inserts or edit a citation at 
point.  More specifically,
                             (concat "/" style)
                           ""))
                     "")
-                  (mapconcat (lambda (k) (concat "@" k)) keys ";"))))))))
+                  (mapconcat (lambda (k) (concat "@" k)) keys "; "))))))))
 
+;;;###autoload
 (defun org-cite-insert (arg)
   "Insert a citation at point.
 Insertion is done according to the processor set in 
`org-cite-insert-processor'.
@@ -1603,7 +1609,7 @@ ARG is the prefix argument received when calling 
interactively the function."
   (let ((name org-cite-insert-processor))
     (cond
      ((null name)
-      (user-error "No processor set to follow citations"))
+      (user-error "No processor set to insert citations"))
      ((not (org-cite--get-processor name))
       (user-error "Unknown processor %S" name))
      ((not (org-cite-processor-has-capability-p name 'insert))
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index 9948008..4464459 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made."
 (defun org-git-version ()
   "The Git version of Org mode.
 Inserted by installing Org or when a release is made."
-   (let ((org-git-version "release_9.5-46-gb71474"))
+   (let ((org-git-version "release_9.5-57-g9bc3a2"))
      org-git-version))
 
 (provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index c2a37e6..83b3d79 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -95,6 +95,7 @@
 (require 'org-keys)
 (require 'ol)
 (require 'oc)
+(require 'oc-basic)
 (require 'org-table)
 
 ;; `org-outline-regexp' ought to be a defconst but is let-bound in
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index ccecdbc..3dc95c9 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -227,6 +227,10 @@ a list of frames to update."
 ;;; Key bindings
 
 (defun tab-bar--key-to-number (key)
+  "Return the tab number represented by KEY.
+If KEY is a symbol 'tab-N', where N is a tab number, the value is N.
+If KEY is \\='current-tab, the value is nil.
+For any other value of KEY, the value is t."
   (cond
    ((null key) t)
    ((eq key 'current-tab) nil)
@@ -235,7 +239,16 @@ a list of frames to update."
         (string-to-number (string-replace "tab-" "" key-name)))))
    (t t)))
 
+(defvar tab-bar-drag-maybe)
+
 (defun tab-bar--event-to-item (posn)
+  "This function extracts extra info from the mouse event at position POSN.
+It returns a list of the form (KEY KEY-BINDING CLOSE-P), where:
+ KEY is a symbol representing a tab, such as \\='tab-1 or \\='current-tab;
+ KEY-BINDING is the binding of KEY;
+ CLOSE-P is non-nil if the mouse event was a click on the close button \"x\",
+   nil otherwise."
+  (setq tab-bar-drag-maybe nil)
   (if (posn-window posn)
       (let ((caption (car (posn-string posn))))
         (when caption
@@ -259,31 +272,40 @@ a list of frames to update."
                (setq column (+ column (length (nth 1 binding))))))
            keymap))))))
 
-(defun tab-bar-mouse-select-tab (event)
+(defun tab-bar-mouse-down-1 (event)
+  "Select the tab at mouse click, or add a new tab on the tab bar.
+Whether this command adds a new tab or selects an existing tab
+depends on whether the click is on the \"+\" button or on an
+existing tab."
   (interactive "e")
   (let* ((item (tab-bar--event-to-item (event-start event)))
          (tab-number (tab-bar--key-to-number (nth 0 item))))
-    ;; Don't close the tab when clicked on the close button.
-    ;; Let `tab-bar-mouse-close-tab-from-button' do this.
-    (unless (nth 2 item)
+    (setq tab-bar-drag-maybe t)
+    ;; Don't close the tab when clicked on the close button.  Also
+    ;; don't add new tab on down-mouse.  Let `tab-bar-mouse-1' do this.
+    (unless (or (eq (car item) 'add-tab) (nth 2 item))
       (if (functionp (nth 1 item))
           (call-interactively (nth 1 item))
         (unless (eq tab-number t)
           (tab-bar-select-tab tab-number))))))
 
-(defun tab-bar-mouse-close-tab-from-button (event)
-  "Close the tab only when clicked on the close button."
+(defun tab-bar-mouse-1 (event)
+  "Close the tab whose \"x\" close button you click.
+See also `tab-bar-mouse-close-tab', which closes the tab
+regardless of where you click on it.  Also add a new tab."
   (interactive "e")
   (let* ((item (tab-bar--event-to-item (event-start event)))
          (tab-number (tab-bar--key-to-number (nth 0 item))))
-    (when (nth 2 item)
-      (unless (eq tab-number t)
-        (tab-bar-close-tab tab-number)))))
+    (cond
+     ((and (eq (car item) 'add-tab) (functionp (nth 1 item)))
+      (call-interactively (nth 1 item)))
+     ((and (nth 2 item) (not (eq tab-number t)))
+      (tab-bar-close-tab tab-number)))))
 
 (defun tab-bar-mouse-close-tab (event)
-  "Close the tab when clicked anywhere on the tab.
-This is in contrast with `tab-bar-mouse-close-tab-from-button'
-that closes only when clicked on the close button."
+  "Close the tab you click on.
+This is in contrast with `tab-bar-mouse-1' that closes a tab
+only when you click on its \"x\" close button."
   (interactive "e")
   (let* ((item (tab-bar--event-to-item (event-start event)))
          (tab-number (tab-bar--key-to-number (nth 0 item))))
@@ -291,6 +313,7 @@ that closes only when clicked on the close button."
       (tab-bar-close-tab tab-number))))
 
 (defun tab-bar-mouse-context-menu (event)
+  "Pop up the context menu for the tab on which you click."
   (interactive "e")
   (let* ((item (tab-bar--event-to-item (event-start event)))
          (tab-number (tab-bar--key-to-number (nth 0 item)))
@@ -330,23 +353,28 @@ that closes only when clicked on the close button."
     (popup-menu menu event)))
 
 (defun tab-bar-mouse-move-tab (event)
+  "Move a tab to a different position on the tab bar.
+This command should be bound to a drag event.  It moves the tab
+at the mouse-down event to the position at mouse-up event."
   (interactive "e")
+  (setq tab-bar-drag-maybe nil)
   (let ((from (tab-bar--key-to-number
                (nth 0 (tab-bar--event-to-item
                        (event-start event)))))
         (to (tab-bar--key-to-number
              (nth 0 (tab-bar--event-to-item
                      (event-end event))))))
-    (unless (or (eq from t) (eq to t))
-      (tab-bar-move-tab-to to from))))
+    (unless (or (eq from to) (eq from t) (eq to t))
+      (tab-bar-move-tab-to
+       (if (null to) (1+ (tab-bar--current-tab-index)) to) from))))
 
 (defvar tab-bar-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [down-mouse-1] 'tab-bar-mouse-select-tab)
+    (define-key map [down-mouse-1] 'tab-bar-mouse-down-1)
     (define-key map [drag-mouse-1] 'tab-bar-mouse-move-tab)
-    (define-key map [mouse-1] 'tab-bar-mouse-close-tab-from-button)
+    (define-key map [mouse-1]      'tab-bar-mouse-1)
     (define-key map [down-mouse-2] 'tab-bar-mouse-close-tab)
-    (define-key map [mouse-2] 'ignore)
+    (define-key map [mouse-2]      'ignore)
     (define-key map [down-mouse-3] 'tab-bar-mouse-context-menu)
 
     (define-key map [mouse-4]     'tab-previous)
@@ -677,11 +705,14 @@ the formatted tab name to display in the tab bar."
   "Template for displaying tab bar items.
 Every item in the list is a function that returns
 a string, or a list of menu-item elements, or nil.
-When you add more items `tab-bar-format-align-right' and
-`tab-bar-format-global' to the end, then after enabling
-`display-time-mode' (or any other mode that uses `global-mode-string')
-it will display time aligned to the right on the tab bar instead of
-the mode line.  Replacing `tab-bar-format-tabs' with
+Adding a function to the list causes the tab bar to show
+that string, or display a menu with those menu items when
+you click on the tab bar.
+If the list ends with `tab-bar-format-align-right' and
+`tab-bar-format-global', then after enabling `display-time-mode'
+(or any other mode that uses `global-mode-string'),
+it will display time aligned to the right on the tab bar instead
+of the mode line.  Replacing `tab-bar-format-tabs' with
 `tab-bar-format-tabs-groups' will group tabs on the tab bar."
   :type 'hook
   :options '(tab-bar-format-menu-global
@@ -700,7 +731,7 @@ the mode line.  Replacing `tab-bar-format-tabs' with
   :version "28.1")
 
 (defun tab-bar-format-menu-global ()
-  "Show global menu on clicking the Menu button."
+  "Produce the Menu button for the tab bar that shows a global menu."
   `((add-tab menu-item (propertize "Menu" 'face 'tab-bar-tab-inactive)
              (lambda (event) (interactive "e")
                (let ((menu (make-sparse-keymap
@@ -717,7 +748,8 @@ the mode line.  Replacing `tab-bar-format-tabs' with
              :help "Global Menu")))
 
 (defun tab-bar-format-history ()
-  "Show back and forward buttons when `tab-bar-history-mode' is enabled.
+  "Produce back and forward buttons for the tab bar.
+These buttons will be shown when `tab-bar-history-mode' is enabled.
 You can hide these buttons by customizing `tab-bar-format' and removing
 `tab-bar-format-history' from it."
   (when tab-bar-history-mode
@@ -731,7 +763,7 @@ You can hide these buttons by customizing `tab-bar-format' 
and removing
        :help "Click to go forward in tab history"))))
 
 (defun tab-bar--format-tab (tab i)
-  "Format TAB using its index I and return the result as a string."
+  "Format TAB using its index I and return the result as a keymap."
   (append
    `((,(intern (format "sep-%i" i)) menu-item ,(tab-bar-separator) ignore))
    (cond
@@ -753,7 +785,7 @@ You can hide these buttons by customizing `tab-bar-format' 
and removing
         ,(alist-get 'close-binding tab))))))
 
 (defun tab-bar-format-tabs ()
-  "Show all tabs."
+  "Produce all the tabs for the tab bar."
   (let ((i 0))
     (mapcan
      (lambda (tab)
@@ -807,6 +839,9 @@ Function gets one argument: a tab."
     (tab-bar-tab-face-default tab)))
 
 (defun tab-bar--format-tab-group (tab i &optional current-p)
+  "Format TAB as a tab that represents a group of tabs.
+The argument I is the tab index, and CURRENT-P is non-nil
+when the tab is current.  Return the result as a keymap."
   (append
    `((,(intern (format "sep-%i" i)) menu-item ,(tab-bar-separator) ignore))
    `((,(intern (format "group-%i" i))
@@ -824,7 +859,7 @@ Function gets one argument: a tab."
       :help "Click to visit group"))))
 
 (defun tab-bar-format-tabs-groups ()
-  "Show tabs with their groups."
+  "Produce tabs for the tab bar grouped according to their groups."
   (let* ((tabs (funcall tab-bar-tabs-function))
          (current-group (funcall tab-bar-tab-group-function
                                  (tab-bar--current-tab-find tabs)))
@@ -868,7 +903,7 @@ Function gets one argument: a tab."
     `((align-right menu-item ,str ignore))))
 
 (defun tab-bar-format-global ()
-  "Format `global-mode-string' to display it in the tab bar.
+  "Produce display of `global-mode-string' in the tab bar.
 When `tab-bar-format-global' is added to `tab-bar-format'
 (possibly appended after `tab-bar-format-align-right'),
 then modes that display information on the mode line
@@ -917,6 +952,7 @@ on the tab bar instead."
 (push '(tabs . frameset-filter-tabs) frameset-filter-alist)
 
 (defun tab-bar--tab (&optional frame)
+  "Make a new tab data structure that can be added to tabs on the FRAME."
   (let* ((tab (tab-bar--current-tab-find nil frame))
          (tab-explicit-name (alist-get 'explicit-name tab))
          (tab-group (alist-get 'group tab))
@@ -951,12 +987,15 @@ on the tab bar instead."
                 (cdr tab)))))
 
 (defun tab-bar--current-tab (&optional tab frame)
+  "Make the current tab data structure from TAB on FRAME."
   (tab-bar--current-tab-make (or tab (tab-bar--current-tab-find nil frame))))
 
 (defun tab-bar--current-tab-make (&optional tab)
-  ;; `tab' here is an argument meaning "use tab as template".  This is
-  ;; necessary when switching tabs, otherwise the destination tab
-  ;; inherits the current tab's `explicit-name' parameter.
+  "Make the current tab data structure from TAB.
+TAB here is an argument meaning \"use tab as template\",
+i.e. the tab is created using data from TAB.  This is
+necessary when switching tabs, otherwise the destination tab
+inherits the current tab's `explicit-name' parameter."
   (let* ((tab-explicit-name (alist-get 'explicit-name tab))
          (tab-group (if tab
                         (alist-get 'group tab)
@@ -979,27 +1018,33 @@ on the tab bar instead."
                 (cdr tab)))))
 
 (defun tab-bar--current-tab-find (&optional tabs frame)
+  ;; Find the current tab as a pointer to its data structure.
   (assq 'current-tab (or tabs (funcall tab-bar-tabs-function frame))))
 
 (defun tab-bar--current-tab-index (&optional tabs frame)
+  ;; Return the index of the current tab.
   (seq-position (or tabs (funcall tab-bar-tabs-function frame))
                 'current-tab (lambda (a b) (eq (car a) b))))
 
 (defun tab-bar--tab-index (tab &optional tabs frame)
+  ;; Return the index of TAB.
   (seq-position (or tabs (funcall tab-bar-tabs-function frame))
                 tab #'eq))
 
 (defun tab-bar--tab-index-by-name (name &optional tabs frame)
+  ;; Return the index of TAB by the its NAME.
   (seq-position (or tabs (funcall tab-bar-tabs-function frame))
                 name (lambda (a b) (equal (alist-get 'name a) b))))
 
 (defun tab-bar--tab-index-recent (nth &optional tabs frame)
+  ;; Return the index of NTH recent tab.
   (let* ((tabs (or tabs (funcall tab-bar-tabs-function frame)))
          (sorted-tabs (tab-bar--tabs-recent tabs frame))
          (tab (nth (1- nth) sorted-tabs)))
     (tab-bar--tab-index tab tabs)))
 
 (defun tab-bar--tabs-recent (&optional tabs frame)
+  ;; Return the list of tabs sorted by recency.
   (let* ((tabs (or tabs (funcall tab-bar-tabs-function frame))))
     (seq-sort-by (lambda (tab) (alist-get 'time tab)) #'>
                  (seq-remove (lambda (tab)
@@ -1089,7 +1134,8 @@ the tab bar."
       (force-mode-line-update))))
 
 (defun tab-bar-switch-to-next-tab (&optional arg)
-  "Switch to ARGth next tab."
+  "Switch to ARGth next tab.
+Interactively, ARG is the prefix numeric argument and defaults to 1."
   (interactive "p")
   (unless (integerp arg)
     (setq arg 1))
@@ -1099,20 +1145,24 @@ the tab bar."
     (tab-bar-select-tab (1+ to-index))))
 
 (defun tab-bar-switch-to-prev-tab (&optional arg)
-  "Switch to ARGth previous tab."
+  "Switch to ARGth previous tab.
+Interactively, ARG is the prefix numeric argument and defaults to 1."
   (interactive "p")
   (unless (integerp arg)
     (setq arg 1))
   (tab-bar-switch-to-next-tab (- arg)))
 
 (defun tab-bar-switch-to-last-tab (&optional arg)
-  "Switch to the last tab or ARGth tab from the end of the tab bar."
+  "Switch to the last tab or ARGth tab from the end of the tab bar.
+Interactively, ARG is the prefix numeric argument; it defaults to 1,
+which means the last tab on the tab bar."
   (interactive "p")
   (tab-bar-select-tab (- (length (funcall tab-bar-tabs-function))
                          (1- (or arg 1)))))
 
 (defun tab-bar-switch-to-recent-tab (&optional arg)
-  "Switch to ARGth most recently visited tab."
+  "Switch to ARGth most recently visited tab.
+Interactively, ARG is the prefix numeric argument and defaults to 1."
   (interactive "p")
   (unless (integerp arg)
     (setq arg 1))
@@ -1160,8 +1210,9 @@ where argument addressing is relative."
 
 (defun tab-bar-move-tab (&optional arg)
   "Move the current tab ARG positions to the right.
-If a negative ARG, move the current tab ARG positions to the left.
-Argument addressing is relative in contrast to `tab-bar-move-tab-to'
+Interactively, ARG is the prefix numeric argument and defaults to 1.
+If ARG is negative, move the current tab ARG positions to the left.
+Argument addressing is relative in contrast to `tab-bar-move-tab-to',
 where argument addressing is absolute."
   (interactive "p")
   (let* ((tabs (funcall tab-bar-tabs-function))
@@ -1171,6 +1222,7 @@ where argument addressing is absolute."
 
 (defun tab-bar-move-tab-backward (&optional arg)
   "Move the current tab ARG positions to the left.
+Interactively, ARG is the prefix numeric argument and defaults to 1.
 Like `tab-bar-move-tab', but moves in the opposite direction."
   (interactive "p")
   (tab-bar-move-tab (- (or arg 1))))
@@ -1181,7 +1233,8 @@ FROM-NUMBER defaults to the current tab number.
 FROM-NUMBER and TO-NUMBER count from 1.
 FROM-FRAME specifies the source frame and defaults to the selected frame.
 TO-FRAME specifies the target frame and defaults the next frame.
-Interactively, ARG selects the ARGth different frame to move to."
+Interactively, ARG selects the ARGth next frame on the same terminal,
+to which to move the tab; ARG defaults to 1."
   (interactive "P")
   (unless from-frame
     (setq from-frame (selected-frame)))
@@ -1209,7 +1262,7 @@ Interactively, ARG selects the ARGth different frame to 
move to."
 
 (defun tab-bar-detach-tab (&optional from-number)
   "Move tab number FROM-NUMBER to a new frame.
-Interactively or without argument, move the current tab."
+FROM-NUMBER defaults to the current tab (which happens interactively)."
   (interactive (list (1+ (tab-bar--current-tab-index))))
   (let* ((tabs (funcall tab-bar-tabs-function))
          (tab-index (1- (or from-number (1+ (tab-bar--current-tab-index 
tabs)))))
@@ -1223,7 +1276,10 @@ Interactively or without argument, move the current tab."
       (tab-bar-close-tab))))
 
 (defun tab-bar-move-window-to-tab ()
-  "Detach the selected window to a new tab."
+  "Move the selected window to a new tab.
+This command removes the selected window from the configuration stored
+on the current tab, and makes a new tab with that window in its
+configuration."
   (interactive)
   (let ((tab-bar-new-tab-choice 'window))
     (tab-bar-new-tab))
@@ -1233,17 +1289,17 @@ Interactively or without argument, move the current 
tab."
 
 
 (defcustom tab-bar-new-tab-to 'right
-  "Defines where to create a new tab.
+  "Where to create a new tab.
 If `leftmost', create as the first tab.
-If `left', create to the left from the current tab.
-If `right', create to the right from the current tab.
+If `left', create to the left of the current tab.
+If `right', create to the right of the current tab.
 If `rightmost', create as the last tab.
 If the value is a function, it should return a number as a position
-on the tab bar specifying where to insert a new tab."
-  :type '(choice (const :tag "First tab" leftmost)
-                 (const :tag "To the left" left)
-                 (const :tag "To the right" right)
-                 (const :tag "Last tab" rightmost)
+on the tab bar specifying where to add a new tab."
+  :type '(choice (const :tag "Add as First" leftmost)
+                 (const :tag "Add to Left" left)
+                 (const :tag "Add to Right" right)
+                 (const :tag "Add as Last" rightmost)
                  (function :tag "Function"))
   :group 'tab-bar
   :version "27.1")
@@ -1262,7 +1318,7 @@ TAB-NUMBER counts from 1.  If no TAB-NUMBER is specified, 
then add
 a new tab at the position specified by `tab-bar-new-tab-to'.
 Negative TAB-NUMBER counts tabs from the end of the tab bar,
 and -1 means the new tab will become the last one.
-Argument addressing is absolute in contrast to `tab-bar-new-tab'
+Argument addressing is absolute in contrast to `tab-bar-new-tab',
 where argument addressing is relative.
 After the tab is created, the hooks in
 `tab-bar-tab-post-open-functions' are run."
@@ -1335,7 +1391,7 @@ If a negative ARG, create a new tab ARG positions to the 
left.
 If ARG is zero, create a new tab in place of the current tab.
 If no ARG is specified, then add a new tab at the position
 specified by `tab-bar-new-tab-to'.
-Argument addressing is relative in contrast to `tab-bar-new-tab-to'
+Argument addressing is relative in contrast to `tab-bar-new-tab-to',
 where argument addressing is absolute.
 If FROM-NUMBER is a tab number, a new tab is created from that tab."
   (interactive "P")
@@ -1362,7 +1418,7 @@ ARG and FROM-NUMBER have the same meaning as in 
`tab-bar-new-tab'."
   "A list of closed tabs to be able to undo their closing.")
 
 (defcustom tab-bar-close-tab-select 'recent
-  "Defines what tab to select after closing the specified tab.
+  "Which tab to make current after closing the specified tab.
 If `left', select the adjacent left tab.
 If `right', select the adjacent right tab.
 If `recent', select the most recently visited tab."
@@ -1373,7 +1429,7 @@ If `recent', select the most recently visited tab."
   :version "27.1")
 
 (defcustom tab-bar-close-last-tab-choice nil
-  "Defines what to do when the last tab is closed.
+  "What to do when the last tab is closed.
 If nil, do nothing and show a message, like closing the last window or frame.
 If `delete-frame', delete the containing frame, as a web browser would do.
 If `tab-bar-mode-disable', disable `tab-bar-mode' so that tabs no longer show
@@ -1398,9 +1454,8 @@ function returns a non-nil value, the tab will not be 
closed."
 
 (defcustom tab-bar-tab-pre-close-functions nil
   "List of functions to call before closing a tab.
-The tab to be closed and a boolean indicating whether or not it
-is the only tab in the frame are supplied as arguments,
-respectively."
+Each function is called with two arguments: the tab to be closed
+and a boolean indicating whether or not it is the only tab on its frame."
   :type '(repeat function)
   :group 'tab-bar
   :version "27.1")
@@ -1409,6 +1464,7 @@ respectively."
   "Close the tab specified by its absolute position TAB-NUMBER.
 If no TAB-NUMBER is specified, then close the current tab and switch
 to the tab specified by `tab-bar-close-tab-select'.
+Interactively, TAB-NUMBER is the prefix numeric argument, and defaults to 1.
 TAB-NUMBER counts from 1.
 Optional TO-NUMBER could be specified to override the value of
 `tab-bar-close-tab-select' programmatically with a position
@@ -1482,7 +1538,8 @@ for the last tab on a frame is determined by
           (message "Deleted tab and switched to %s" 
tab-bar-close-tab-select))))))
 
 (defun tab-bar-close-tab-by-name (name)
-  "Close the tab by NAME."
+  "Close the tab given its NAME.
+Interactively, prompt for NAME."
   (interactive
    (list (completing-read "Close tab by name: "
                           (mapcar (lambda (tab)
@@ -1491,8 +1548,9 @@ for the last tab on a frame is determined by
   (tab-bar-close-tab (1+ (tab-bar--tab-index-by-name name))))
 
 (defun tab-bar-close-other-tabs (&optional tab-number)
-  "Close all tabs on the selected frame, except TAB-NUMBER.
-TAB-NUMBER counts from 1 and defaults to the current tab."
+  "Close all tabs on the selected frame, except the tab TAB-NUMBER.
+TAB-NUMBER counts from 1 and defaults to the current tab (which
+happens interactively)."
   (interactive)
   (let* ((tabs (funcall tab-bar-tabs-function))
          (current-index (tab-bar--current-tab-index tabs))
@@ -1558,9 +1616,12 @@ TAB-NUMBER counts from 1 and defaults to the current 
tab."
 
 
 (defun tab-bar-rename-tab (name &optional tab-number)
-  "Rename the tab specified by its absolute position TAB-NUMBER.
+  "Give the tab specified by its absolute position TAB-NUMBER a new NAME.
 If no TAB-NUMBER is specified, then rename the current tab.
+Interactively, TAB-NUMBER is the prefix numeric argument, and defaults
+to the current tab.
 TAB-NUMBER counts from 1.
+Interactively, prompt for the new NAME.
 If NAME is the empty string, then use the automatic name
 function `tab-bar-tab-name-function'."
   (interactive
@@ -1588,7 +1649,8 @@ function `tab-bar-tab-name-function'."
       (message "Renamed tab to '%s'" tab-new-name))))
 
 (defun tab-bar-rename-tab-by-name (tab-name new-name)
-  "Rename the tab named TAB-NAME.
+  "Rename the tab named TAB-NAME to NEW-NAME.
+Interactively, prompt for TAB-NAME and NEW-NAME.
 If NEW-NAME is the empty string, then use the automatic name
 function `tab-bar-tab-name-function'."
   (interactive
@@ -1605,7 +1667,7 @@ function `tab-bar-tab-name-function'."
 ;;; Tab groups
 
 (defun tab-bar-move-tab-to-group (&optional tab)
-  "Relocate TAB (or the current tab) closer to its group."
+  "Relocate TAB (by default, the current tab) closer to its group."
   (interactive)
   (let* ((tabs (funcall tab-bar-tabs-function))
          (tab (or tab (tab-bar--current-tab-find tabs)))
@@ -1643,6 +1705,8 @@ The current tab is supplied as an argument."
 (defun tab-bar-change-tab-group (group-name &optional tab-number)
   "Add the tab specified by its absolute position TAB-NUMBER to GROUP-NAME.
 If no TAB-NUMBER is specified, then set the GROUP-NAME for the current tab.
+Interactively, TAB-NUMBER is the prefix numeric argument, and the command
+prompts for GROUP-NAME.
 TAB-NUMBER counts from 1.
 If GROUP-NAME is the empty string, then remove the tab from any group.
 While using this command, you might also want to replace
@@ -1680,7 +1744,8 @@ While using this command, you might also want to replace
       (message "Set tab group to '%s'" group-new-name))))
 
 (defun tab-bar-close-group-tabs (group-name)
-  "Close all tabs that belong to GROUP-NAME on the selected frame."
+  "Close all tabs that belong to GROUP-NAME on the selected frame.
+Interactively, prompt for GROUP-NAME."
   (interactive
    (let ((group-name (funcall tab-bar-tab-group-function
                               (tab-bar--current-tab-find))))
@@ -1727,7 +1792,7 @@ While using this command, you might also want to replace
 
 (defun tab-bar--history-pre-change ()
   (setq tab-bar-history-old-minibuffer-depth (minibuffer-depth))
-  ;; Store wc before possibly entering the minibuffer
+  ;; Store window-configuration before possibly entering the minibuffer.
   (when (zerop tab-bar-history-old-minibuffer-depth)
     (setq tab-bar-history-old
           `((wc . ,(current-window-configuration))
@@ -1736,7 +1801,8 @@ While using this command, you might also want to replace
 (defun tab-bar--history-change ()
   (when (and (not tab-bar-history-omit)
              tab-bar-history-old
-             ;; Store wc before possibly entering the minibuffer
+             ;; Store window-configuration before possibly entering
+             ;; the minibuffer.
              (zerop tab-bar-history-old-minibuffer-depth))
     (puthash (selected-frame)
              (seq-take (cons tab-bar-history-old
@@ -1928,12 +1994,16 @@ Letters do not insert themselves; instead, they are 
commands.
           nil))))
 
 (defun tab-switcher-next-line (&optional arg)
+  "Move to ARGth next line in the list of tabs.
+Interactively, ARG is the prefix numeric argument and defaults to 1."
   (interactive "p")
   (forward-line arg)
   (beginning-of-line)
   (move-to-column tab-switcher-column))
 
 (defun tab-switcher-prev-line (&optional arg)
+  "Move to ARGth previous line in the list of tabs.
+Interactively, ARG is the prefix numeric argument and defaults to 1."
   (interactive "p")
   (forward-line (- arg))
   (beginning-of-line)
@@ -1941,7 +2011,7 @@ Letters do not insert themselves; instead, they are 
commands.
 
 (defun tab-switcher-unmark (&optional backup)
   "Cancel requested operations on window configuration on this line and move 
down.
-Optional prefix arg means move up."
+With prefix arg, move up instead."
   (interactive "P")
   (beginning-of-line)
   (move-to-column tab-switcher-column)
@@ -1961,7 +2031,7 @@ Optional prefix arg means move up."
 
 (defun tab-switcher-delete (&optional arg)
   "Mark window configuration on this line to be deleted by 
\\<tab-switcher-mode-map>\\[tab-switcher-execute] command.
-Prefix arg is how many window configurations to delete.
+Prefix arg says how many window configurations to delete.
 Negative arg means delete backwards."
   (interactive "p")
   (let ((buffer-read-only nil))
@@ -1986,7 +2056,7 @@ Then move up one line.  Prefix arg means move that many 
lines."
   (tab-switcher-delete (- (or arg 1))))
 
 (defun tab-switcher-delete-from-list (tab)
-  "Delete the window configuration from both lists."
+  "Delete the window configuration from the list of tabs."
   (push `((frame . ,(selected-frame))
           (index . ,(tab-bar--tab-index tab))
           (tab . ,tab))
@@ -2014,8 +2084,8 @@ Then move up one line.  Prefix arg means move that many 
lines."
 
 (defun tab-switcher-select ()
   "Select this line's window configuration.
-This command deletes and replaces all the previously existing windows
-in the selected frame."
+This command replaces all the existing windows in the selected frame
+with those specified by the selected window configuration."
   (interactive)
   (let* ((to-tab (tab-switcher-current-tab t)))
     (kill-buffer (current-buffer))
@@ -2041,8 +2111,8 @@ in the selected frame."
    (t (list (selected-frame)))))
 
 (defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames 
ignore-current-tab)
-  "Return a tab owning a window whose buffer is BUFFER-OR-NAME.
-BUFFER-OR-NAME may be a buffer or a buffer name and defaults to
+  "Return the tab that owns the window whose buffer is BUFFER-OR-NAME.
+BUFFER-OR-NAME may be a buffer or a buffer name, and defaults to
 the current buffer.
 
 The optional argument ALL-FRAMES specifies the frames to consider:
@@ -2090,7 +2160,7 @@ Otherwise, prefer buffers of the current tab."
        (tab-bar--reusable-frames all-frames)))))
 
 (defun display-buffer-in-tab (buffer alist)
-  "Display BUFFER in a tab.
+  "Display BUFFER in a tab using display actions in ALIST.
 ALIST is an association list of action symbols and values.  See
 Info node `(elisp) Buffer Display Action Alists' for details of
 such alists.
@@ -2098,8 +2168,8 @@ such alists.
 If ALIST contains a `tab-name' entry, it creates a new tab with that name and
 displays BUFFER in a new tab.  If a tab with this name already exists, it
 switches to that tab before displaying BUFFER.  The `tab-name' entry can be
-a function, then it is called with two arguments: BUFFER and ALIST, and
-should return the tab name.  When a `tab-name' entry is omitted, create
+a function, in which case it is called with two arguments: BUFFER and ALIST,
+and should return the tab name.  When a `tab-name' entry is omitted, create
 a new tab without an explicit name.
 
 The ALIST entry `tab-group' (string or function) defines the tab group.
@@ -2149,7 +2219,7 @@ indirectly called by the latter."
           (display-buffer-in-new-tab buffer alist))))))
 
 (defun display-buffer-in-new-tab (buffer alist)
-  "Display BUFFER in a new tab.
+  "Display BUFFER in a new tab using display actions in ALIST.
 ALIST is an association list of action symbols and values.  See
 Info node `(elisp) Buffer Display Action Alists' for details of
 such alists.
@@ -2159,9 +2229,9 @@ without checking if a suitable tab already exists.
 
 If ALIST contains a `tab-name' entry, it creates a new tab with that name
 and displays BUFFER in a new tab.  The `tab-name' entry can be a function,
-then it is called with two arguments: BUFFER and ALIST, and should return
-the tab name.  When a `tab-name' entry is omitted, create a new tab without
-an explicit name.
+in which case it is called with two arguments: BUFFER and ALIST, and should
+return the tab name.  When a `tab-name' entry is omitted, create a new tab
+without an explicit name.
 
 The ALIST entry `tab-group' (string or function) defines the tab group.
 
@@ -2183,19 +2253,23 @@ indirectly called by the latter."
         (tab-bar-change-tab-group tab-group)))
     (window--display-buffer buffer (selected-window) 'tab alist)))
 
-(defun switch-to-buffer-other-tab (buffer-or-name &optional norecord)
+(defun switch-to-buffer-other-tab (buffer-or-name &optional _norecord)
   "Switch to buffer BUFFER-OR-NAME in another tab.
-Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab."
+Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab.
+Interactively, prompt for the buffer to switch to."
+  (declare (advertised-calling-convention (buffer-or-name) "28.1"))
   (interactive
    (list (read-buffer-to-switch "Switch to buffer in other tab: ")))
   (display-buffer (window-normalize-buffer-to-switch-to buffer-or-name)
                   '((display-buffer-in-tab)
-                    (inhibit-same-window . nil))
-                  norecord))
+                    (inhibit-same-window . nil))))
 
 (defun find-file-other-tab (filename &optional wildcards)
   "Edit file FILENAME, in another tab.
-Like \\[find-file-other-frame] (which see), but creates a new tab."
+Like \\[find-file-other-frame] (which see), but creates a new tab.
+Interactively, prompt for FILENAME.
+If WILDCARDS is non-nil, FILENAME can include widcards, and all matching
+files will be visited."
   (interactive
    (find-file-read-args "Find file in other tab: "
                         (confirm-nonexistent-file-or-buffer)))
@@ -2212,7 +2286,10 @@ Like \\[find-file-other-frame] (which see), but creates 
a new tab."
   "Edit file FILENAME, in another tab, but don't allow changes.
 Like \\[find-file-other-frame] (which see), but creates a new tab.
 Like \\[find-file-other-tab], but marks buffer as read-only.
-Use \\[read-only-mode] to permit editing."
+Use \\[read-only-mode] to permit editing.
+Interactively, prompt for FILENAME.
+If WILDCARDS is non-nil, FILENAME can include widcards, and all matching
+files will be visited."
   (interactive
    (find-file-read-args "Find file read-only in other tab: "
                         (confirm-nonexistent-file-or-buffer)))
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 78c06bb..5affae7 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -262,13 +262,14 @@ If nil, don't show it at all."
 
 (defcustom tab-line-tab-name-function #'tab-line-tab-name-buffer
   "Function to get a tab name.
-Function gets two arguments: tab to get name for and a list of tabs
-to display.  By default, use function `tab-line-tab-name'."
+The function is called with one or two arguments: the buffer or
+another object whose tab's name is requested, and, optionally,
+the list of all tabs."
   :type '(choice (const :tag "Buffer name"
                         tab-line-tab-name-buffer)
                  (const :tag "Truncated buffer name"
                         tab-line-tab-name-truncated-buffer)
-                 (function  :tag "Function"))
+                 (function :tag "Function"))
   :initialize 'custom-initialize-default
   :set (lambda (sym val)
          (set-default sym val)
@@ -294,9 +295,9 @@ to `tab-line-tab-name-truncated-buffer'."
 (defvar tab-line-tab-name-ellipsis t)
 
 (defun tab-line-tab-name-truncated-buffer (buffer &optional _buffers)
-  "Generate tab name from BUFFER.
+  "Generate tab name from BUFFER, truncating it as needed.
 Truncate it to the length specified by `tab-line-tab-name-truncated-max'.
-Append ellipsis `tab-line-tab-name-ellipsis' in this case."
+If truncated, append ellipsis per `tab-line-tab-name-ellipsis'."
   (let ((tab-name (buffer-name buffer)))
     (if (< (length tab-name) tab-line-tab-name-truncated-max)
         tab-name
@@ -343,7 +344,7 @@ Used only for `tab-line-tabs-mode-buffers' and 
`tab-line-tabs-buffer-groups'.")
                                 (buffer-list)))))
 
 (defun tab-line-tabs-mode-buffers ()
-  "Return a list of buffers with the same major mode with current buffer."
+  "Return a list of buffers with the same major mode as the current buffer."
   (let ((mode major-mode))
     (seq-sort-by #'buffer-name #'string<
                  (seq-filter (lambda (b) (with-current-buffer b
@@ -351,12 +352,12 @@ Used only for `tab-line-tabs-mode-buffers' and 
`tab-line-tabs-buffer-groups'.")
                              (funcall tab-line-tabs-buffer-list-function)))))
 
 (defvar tab-line-tabs-buffer-group-function nil
-  "Function to put a buffer to the group.
-Takes a buffer as arg and should return a group name as string.
-When the return value is nil, filter out the buffer.")
+  "Function to add a buffer to the appropriate group of tabs.
+Takes a buffer as arg and should return a group name as a string.
+If the return value is nil, the buffer should be filtered out.")
 
 (defvar tab-line-tabs-buffer-group-sort-function nil
-  "Function to sort buffers in group.")
+  "Function to sort buffers in a group.")
 
 (defvar tab-line-tabs-buffer-groups-sort-function #'string<
   "Function to sort group names.")
@@ -364,7 +365,9 @@ When the return value is nil, filter out the buffer.")
 (defvar tab-line-tabs-buffer-groups mouse-buffer-menu-mode-groups
   "How to group various major modes together in the tab line.
 Each element has the form (REGEXP . GROUPNAME).
-If the major mode's name string matches REGEXP, use GROUPNAME instead.")
+If the major mode's name matches REGEXP, it belongs to GROUPNAME.
+The default is for each major mode to have a separate group
+named the same as the mode.")
 
 (defun tab-line-tabs-buffer-group-name (&optional buffer)
   (if (functionp tab-line-tabs-buffer-group-function)
@@ -460,8 +463,11 @@ variable `tab-line-tabs-function'."
 
 (defcustom tab-line-tab-name-format-function #'tab-line-tab-name-format-default
   "Function to format a tab name.
-Function gets two arguments: the tab and a list of all tabs, and
-should return the formatted tab name to display in the tab line."
+The function will be called two arguments: the tab whose name to format,
+and the list of all the tabs; it should return the formatted tab name
+to display in the tab line.
+The first argument could also be a different object, for example the buffer
+which the tab will represent."
   :type 'function
   :initialize 'custom-initialize-default
   :set (lambda (sym val)
@@ -471,6 +477,7 @@ should return the formatted tab name to display in the tab 
line."
   :version "28.1")
 
 (defun tab-line-tab-name-format-default (tab tabs)
+  "Default function to use as `tab-line-tab-name-format-function', which see."
   (let* ((buffer-p (bufferp tab))
          (selected-p (if buffer-p
                          (eq tab (window-buffer))
@@ -503,7 +510,8 @@ should return the formatted tab name to display in the tab 
line."
              mouse-face tab-line-highlight))))
 
 (defun tab-line-format-template (tabs)
-  "Template for displaying tab line for selected window."
+  "Template of the format for displaying tab line for selected window.
+This is used by `tab-line-format'."
   (let* ((separator (or tab-line-separator (if window-system " " "|")))
          (hscroll (window-parameter nil 'tab-line-hscroll))
          (strings
@@ -535,7 +543,8 @@ should return the formatted tab name to display in the tab 
line."
 
 (defun tab-line-tab-face-inactive-alternating (tab tabs face _buffer-p 
selected-p)
   "Return FACE for TAB in TABS with alternation.
-When TAB is an inactive buffer and is even-numbered, make FACE
+SELECTED-P nil means TAB is not the selected tab.
+When TAB is not selected and is even-numbered, make FACE
 inherit from `tab-line-tab-inactive-alternate'.  For use in
 `tab-line-tab-face-functions'."
   (when (and (not selected-p) (cl-evenp (cl-position tab tabs)))
@@ -543,8 +552,8 @@ inherit from `tab-line-tab-inactive-alternate'.  For use in
   face)
 
 (defun tab-line-tab-face-special (tab _tabs face buffer-p _selected-p)
-  "Return FACE for TAB according to whether it's special.
-When TAB is a non-file-backed buffer, make FACE inherit from
+  "Return FACE for TAB according to whether its buffer is special.
+When TAB is a non-file-visiting buffer, make FACE inherit from
 `tab-line-tab-special'.  For use in
 `tab-line-tab-face-functions'."
   (when (and buffer-p (not (buffer-file-name tab)))
@@ -552,7 +561,7 @@ When TAB is a non-file-backed buffer, make FACE inherit from
   face)
 
 (defun tab-line-tab-face-modified (tab _tabs face buffer-p _selected-p)
-  "Return FACE for TAB according to whether it's modified.
+  "Return FACE for TAB according to whether its buffer is modified.
 When TAB is a modified, file-backed buffer, make FACE inherit
 from `tab-line-tab-modified'.  For use in
 `tab-line-tab-face-functions'."
@@ -570,7 +579,7 @@ For use in `tab-line-tab-face-functions'."
 (defvar tab-line-auto-hscroll)
 
 (defun tab-line-format ()
-  "Template for displaying tab line for selected window."
+  "Format for displaying the tab line of the selected window."
   (let* ((tabs (funcall tab-line-tabs-function))
          (cache-key (list tabs
                           ;; handle buffer renames
@@ -598,7 +607,7 @@ For use in `tab-line-tab-face-functions'."
 
 (defcustom tab-line-auto-hscroll t
   "Allow or disallow automatic horizontal scrolling of the tab line.
-Non-nil means the tab line are automatically scrolled horizontally to make
+Non-nil means the tab lines are automatically scrolled horizontally to make
 the selected tab visible."
   :type 'boolean
   :group 'tab-line
@@ -694,12 +703,16 @@ the selected tab visible."
       (force-mode-line-update t))))
 
 (defun tab-line-hscroll-right (&optional arg event)
+  "Scroll the tab line ARG positions to the right.
+Interactively, ARG is the prefix numeric argument and defaults to 1."
   (interactive (list current-prefix-arg last-nonmenu-event))
   (let ((window (and (listp event) (posn-window (event-start event)))))
     (tab-line-hscroll arg window)
     (force-mode-line-update window)))
 
 (defun tab-line-hscroll-left (&optional arg event)
+  "Scroll the tab line ARG positions to the left.
+Interactively, ARG is the prefix numeric argument and defaults to 1."
   (interactive (list current-prefix-arg last-nonmenu-event))
   (let ((window (and (listp event) (posn-window (event-start event)))))
     (tab-line-hscroll (- (or arg 1)) window)
@@ -707,10 +720,10 @@ the selected tab visible."
 
 
 (defun tab-line-new-tab (&optional event)
-  "Add a new tab to the tab line.
-Usually is invoked by clicking on the plus-shaped button.
-But any switching to other buffer also adds a new tab
-corresponding to the switched buffer."
+  "Add a new tab to the selected-window's tab line.
+This command is usually invoked by clicking on the plus-shaped button
+on the tab line.  Switching to another buffer also adds a new tab
+corresponding to the new buffer shown in the window."
   (interactive (list last-nonmenu-event))
   (if (functionp tab-line-new-tab-choice)
       (funcall tab-line-new-tab-choice)
@@ -723,9 +736,9 @@ corresponding to the switched buffer."
         (tmm-prompt (mouse-buffer-menu-keymap))))))
 
 (defun tab-line-select-tab (&optional event)
-  "Switch to the selected tab.
+  "Switch to the buffer specified by the tab on which you click.
 This command maintains the original order of prev/next buffers.
-So for example, switching to a previous tab is equivalent to
+So, for example, switching to a previous tab is equivalent to
 using the `previous-buffer' command."
   (interactive "e")
   (let* ((posnp (event-start event))
@@ -771,7 +784,7 @@ when `tab-line-tabs-function' is 
`tab-line-tabs-window-buffers'."
   :version "28.1")
 
 (defun tab-line-switch-to-prev-tab (&optional event)
-  "Switch to the previous tab.
+  "Switch to the previous tab's buffer.
 Its effect is the same as using the `previous-buffer' command
 (\\[previous-buffer])."
   (interactive (list last-nonmenu-event))
@@ -795,7 +808,7 @@ Its effect is the same as using the `previous-buffer' 
command
             (switch-to-buffer buffer)))))))
 
 (defun tab-line-switch-to-next-tab (&optional event)
-  "Switch to the next tab.
+  "Switch to the next tab's buffer.
 Its effect is the same as using the `next-buffer' command
 (\\[next-buffer])."
   (interactive (list last-nonmenu-event))
@@ -820,9 +833,9 @@ Its effect is the same as using the `next-buffer' command
 
 
 (defcustom tab-line-close-tab-function 'bury-buffer
-  "Defines what to do on closing the tab.
+  "What to do upon closing a tab on the tab line.
 If `bury-buffer', put the tab's buffer at the end of the list of all
-buffers that effectively hides the buffer's tab from the tab line.
+buffers, which effectively hides the buffer's tab from the tab line.
 If `kill-buffer', kills the tab's buffer.
 When a function, it is called with the tab as its argument.
 This option is useful when `tab-line-tabs-function' has the value
@@ -835,9 +848,9 @@ This option is useful when `tab-line-tabs-function' has the 
value
 
 (defun tab-line-close-tab (&optional event)
   "Close the selected tab.
-Usually is invoked by clicking on the close button on the right side
-of the tab.  This command buries the buffer, so it goes out of sight
-from the tab line."
+This command is usually invoked by clicking on the close button on the
+right side of the tab.  This command buries the buffer, so it goes out of
+sight of the tab line."
   (interactive (list last-nonmenu-event))
   (let* ((posnp (and (listp event) (event-start event)))
          (window (and posnp (posn-window posnp)))
@@ -860,7 +873,7 @@ from the tab line."
       (force-mode-line-update))))
 
 (defun tab-line-tab-context-menu (&optional event)
-  "Pop up context menu for the tab."
+  "Pop up the context menu for a tab-line tab."
   (interactive "e")
   (let ((menu (make-sparse-keymap (propertize "Context Menu" 'hide t))))
     (define-key-after menu [close]
@@ -868,7 +881,7 @@ from the tab line."
     (popup-menu menu event)))
 
 (defun tab-line-context-menu (&optional event)
-  "Pop up context menu for the tab line."
+  "Pop up the context menu for the tab line."
   (interactive "e")
   (let ((menu (make-sparse-keymap (propertize "Context Menu" 'hide t))))
     (define-key-after menu [close]
@@ -878,13 +891,15 @@ from the tab line."
 
 ;;;###autoload
 (define-minor-mode tab-line-mode
-  "Toggle display of window tab line in the buffer."
+  "Toggle display of tab line in the windows displaying the current buffer."
   :lighter nil
   (setq tab-line-format (when tab-line-mode '(:eval (tab-line-format)))))
 
 (defcustom tab-line-exclude-modes
   '(completion-list-mode)
-  "List of major modes in which the tab line is not enabled."
+  "List of major modes for which the tab-line display is not enabled.
+Buffers under any of these major modes will not show the tab line in
+their windows, even if `global-tab-line-mode' is enabled."
   :type '(repeat symbol)
   :group 'tab-line
   :version "27.1")
@@ -893,7 +908,12 @@ from the tab line."
 (defvar-local tab-line-exclude nil)
 
 (defun tab-line-mode--turn-on ()
-  "Turn on `tab-line-mode'."
+  "Turn on `tab-line-mode' in all pertinent buffers.
+Temporary buffers, buffers whose names begin with a space, buffers
+under major modes that are either mentioned in `tab-line-exclude-mode'
+or have a non-nil `tab-line-exclude' property on their symbol,
+and buffers that have a non-nil buffer-local value
+of `tab-line-exclude', are exempt from `tab-line-mode'."
   (unless (or (minibufferp)
               (string-match-p "\\` " (buffer-name))
               (memq major-mode tab-line-exclude-modes)
diff --git a/src/image.c b/src/image.c
index 470409c..ff05741 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9995,10 +9995,16 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   if (!STRINGP (lcss))
     {
       /* Generate the CSS for the SVG image.  */
-      const char *css_spec = "svg{font-family:\"%s\";font-size:%4dpx}";
-      int css_len = strlen (css_spec) + strlen (img->face_font_family);
+      /* FIXME: The below calculations leave enough space for a font
+        size up to 9999, if it overflows we just throw an error but
+        should probably increase the buffer size.  */
+      const char *css_spec = "svg{font-family:\"%s\";font-size:%dpx}";
+      int css_len = strlen (css_spec) + strlen (img->face_font_family) + 1;
       css = xmalloc (css_len);
-      snprintf (css, css_len, css_spec, img->face_font_family, 
img->face_font_size);
+      if (css_len <= snprintf (css, css_len, css_spec,
+                              img->face_font_family, img->face_font_size))
+       goto rsvg_error;
+
       rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), 
NULL);
     }
   else
@@ -10156,12 +10162,11 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
 
     wrapped_contents = xmalloc (buffer_size);
 
-    if (!wrapped_contents
-        || buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
-                                    foreground & 0xFFFFFF, width, height,
-                                    viewbox_width, viewbox_height,
-                                    background & 0xFFFFFF,
-                                    SSDATA (encoded_contents)))
+    if (buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
+                                foreground & 0xFFFFFF, width, height,
+                                viewbox_width, viewbox_height,
+                                background & 0xFFFFFF,
+                                SSDATA (encoded_contents)))
       goto rsvg_error;
 
     wrapped_size = strlen (wrapped_contents);
diff --git a/src/nsfns.m b/src/nsfns.m
index 906c5c9..797d0ce 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -609,13 +609,72 @@ ns_set_menu_bar_lines (struct frame *f, Lisp_Object 
value, Lisp_Object oldval)
     }
 }
 
+void
+ns_change_tab_bar_height (struct frame *f, int height)
+{
+  int unit = FRAME_LINE_HEIGHT (f);
+  int old_height = FRAME_TAB_BAR_HEIGHT (f);
+  int lines = (height + unit - 1) / unit;
+  Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+
+  /* Make sure we redisplay all windows in this frame.  */
+  fset_redisplay (f);
+
+  /* Recalculate tab bar and frame text sizes.  */
+  FRAME_TAB_BAR_HEIGHT (f) = height;
+  FRAME_TAB_BAR_LINES (f) = lines;
+  store_frame_param (f, Qtab_bar_lines, make_fixnum (lines));
+
+  if (FRAME_NS_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0)
+    {
+      clear_frame (f);
+      clear_current_matrices (f);
+    }
+
+  if ((height < old_height) && WINDOWP (f->tab_bar_window))
+    clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix);
+
+  if (!f->tab_bar_resized)
+    {
+      /* As long as tab_bar_resized is false, effectively try to change
+        F's native height.  */
+      if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
+       adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+                          1, false, Qtab_bar_lines);
+      else
+       adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines);
+
+      f->tab_bar_resized = f->tab_bar_redisplayed;
+    }
+  else
+    /* Any other change may leave the native size of F alone.  */
+    adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines);
+
+  /* adjust_frame_size might not have done anything, garbage frame
+     here.  */
+  adjust_frame_glyphs (f);
+  SET_FRAME_GARBAGED (f);
+}
 
 /* tabbar support */
 static void
 ns_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 {
-  /* Currently unimplemented.  */
-  NSTRACE ("ns_set_tab_bar_lines");
+  int olines = FRAME_TAB_BAR_LINES (f);
+  int nlines;
+
+  /* Treat tab bars like menu bars.  */
+  if (FRAME_MINIBUF_ONLY_P (f))
+    return;
+
+  /* Use VALUE only if an int >= 0.  */
+  if (RANGED_FIXNUMP (0, value, INT_MAX))
+    nlines = XFIXNAT (value);
+  else
+    nlines = 0;
+
+  if (nlines != olines && (olines == 0 || nlines == 0))
+    ns_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
 }
 
 
diff --git a/src/nsterm.h b/src/nsterm.h
index 46733e6..4bbcf43 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -1136,6 +1136,7 @@ extern void ns_implicitly_set_name (struct frame *f, 
Lisp_Object arg,
                                     Lisp_Object oldval);
 extern void ns_set_scroll_bar_default_width (struct frame *f);
 extern void ns_set_scroll_bar_default_height (struct frame *f);
+extern void ns_change_tab_bar_height (struct frame *f, int height);
 extern const char *ns_get_string_resource (void *_rdb,
                                            const char *name,
                                            const char *class);
diff --git a/src/nsterm.m b/src/nsterm.m
index a6c2e75..c6f80f8 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2721,11 +2721,10 @@ ns_clear_under_internal_border (struct frame *f)
 
   if (FRAME_LIVE_P (f) && FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
     {
-      int border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
-      NSView *view = FRAME_NS_VIEW (f);
-      NSRect edge_rect, frame_rect = [view bounds];
-      NSRectEdge edge[] = {NSMinXEdge, NSMinYEdge, NSMaxXEdge, NSMaxYEdge};
-
+      int border = FRAME_INTERNAL_BORDER_WIDTH (f);
+      int width = FRAME_PIXEL_WIDTH (f);
+      int height = FRAME_PIXEL_HEIGHT (f);
+      int margin = FRAME_TOP_MARGIN_HEIGHT (f);
       int face_id =
         (FRAME_PARENT_FRAME (f)
          ? (!NILP (Vface_remapping_alist)
@@ -2747,12 +2746,12 @@ ns_clear_under_internal_border (struct frame *f)
 
       ns_focus (f, NULL, 1);
       [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
-      for (int i = 0; i < 4 ; i++)
-        {
-          NSDivideRect (frame_rect, &edge_rect, &frame_rect, border_width, 
edge[i]);
 
-          NSRectFill (edge_rect);
-        }
+      NSRectFill (NSMakeRect (0, margin, width, border));
+      NSRectFill (NSMakeRect (0, 0, border, height));
+      NSRectFill (NSMakeRect (0, margin, width, border));
+      NSRectFill (NSMakeRect (width - border, 0, border, height));
+      NSRectFill (NSMakeRect (0, height - border, width, border));
       ns_unfocus (f);
     }
 }
@@ -5066,6 +5065,7 @@ ns_create_terminal (struct ns_display_info *dpyinfo)
   terminal->free_pixmap = ns_free_pixmap;
   terminal->delete_frame_hook = ns_destroy_window;
   terminal->delete_terminal_hook = ns_delete_terminal;
+  terminal->change_tab_bar_height_hook = ns_change_tab_bar_height;
   /* Other hooks are NULL by default.  */
 
   return terminal;
@@ -6675,7 +6675,27 @@ not_in_argv (NSString *arg)
     }
   else
     {
-      emacs_event->kind = MOUSE_CLICK_EVENT;
+      Lisp_Object tab_bar_arg = Qnil;
+      bool tab_bar_p = false;
+
+      if (WINDOWP (emacsframe->tab_bar_window)
+         && WINDOW_TOTAL_LINES (XWINDOW (emacsframe->tab_bar_window)))
+       {
+         Lisp_Object window;
+         int x = lrint (p.x);
+         int y = lrint (p.y);
+
+         window = window_from_coordinates (emacsframe, x, y, 0, true, true);
+         tab_bar_p = EQ (window, emacsframe->tab_bar_window);
+
+         if (tab_bar_p)
+           tab_bar_arg = handle_tab_bar_click (emacsframe, x, y, 
EV_UDMODIFIERS (theEvent) & down_modifier,
+                                               EV_MODIFIERS (theEvent) | 
EV_UDMODIFIERS (theEvent));
+       }
+
+      if (!(tab_bar_p && NILP (tab_bar_arg)))
+       emacs_event->kind = MOUSE_CLICK_EVENT;
+      emacs_event->arg = tab_bar_arg;
       emacs_event->code = EV_BUTTON (theEvent);
       emacs_event->modifiers = EV_MODIFIERS (theEvent)
                              | EV_UDMODIFIERS (theEvent);
diff --git a/src/window.c b/src/window.c
index 9845fbb..e801ff8 100644
--- a/src/window.c
+++ b/src/window.c
@@ -765,6 +765,19 @@ selected one.  */)
 {
   return make_fixnum (decode_live_window (window)->use_time);
 }
+
+DEFUN ("window-bump-use-time", Fwindow_bump_use_time,
+       Swindow_bump_use_time, 0, 1, 0,
+       doc: /* Mark WINDOW as having been most recently used.
+WINDOW must be a live window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  struct window *w = decode_live_window (window);
+
+  w->use_time = ++window_select_count;
+
+  return Qnil;
+}
 
 DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
        doc: /* Return the width of window WINDOW in pixels.
@@ -8122,18 +8135,6 @@ and scrolling positions.  */)
     return Qt;
   return Qnil;
 }
-
-DEFUN ("window-bump-use-time", Fwindow_bump_use_time,
-       Swindow_bump_use_time, 1, 1, 0,
-       doc: /* Mark WINDOW as having been recently used.  */)
-  (Lisp_Object window)
-{
-  struct window *w = decode_valid_window (window);
-
-  w->use_time = ++window_select_count;
-  return Qnil;
-}
-
 
 
 static void init_window_once_for_pdumper (void);
diff --git a/src/xdisp.c b/src/xdisp.c
index 783ef39..578458b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -33780,7 +33780,13 @@ note_mouse_highlight (struct frame *f, int x, int y)
   if (EQ (window, f->tab_bar_window))
     {
       note_tab_bar_highlight (f, x, y);
-      return;
+      if (tab_bar_drag_maybe)
+       {
+         cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
+         goto set_cursor;
+       }
+      else
+       return;
     }
 #endif
 
@@ -35910,6 +35916,10 @@ When nil, mouse-movement events will not be generated 
as long as the
 mouse stays within the extent of a single glyph (except for images).  */);
   mouse_fine_grained_tracking = false;
 
+  DEFVAR_BOOL ("tab-bar-drag-maybe", tab_bar_drag_maybe,
+    doc: /* Non-nil when maybe dragging tab bar item.  */);
+  tab_bar_drag_maybe = false;
+
   DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
     doc: /* Non-nil to skip redisplay in initial frame.
 The initial frame is not displayed anywhere, so skipping it is
diff --git a/test/lisp/cedet/semantic/bovine/gcc-tests.el 
b/test/lisp/cedet/semantic/bovine/gcc-tests.el
index 93677d6..d049f95 100644
--- a/test/lisp/cedet/semantic/bovine/gcc-tests.el
+++ b/test/lisp/cedet/semantic/bovine/gcc-tests.el
@@ -124,6 +124,11 @@ gcc version 2.95.2 19991024 (release)"
   "Test the output parser against the machine currently running Emacs."
   (skip-unless (executable-find "gcc"))
   (let ((semantic-gcc-test-strings (list (semantic-gcc-query "gcc" "-v"))))
-    (semantic-gcc-test-output-parser)))
+    ;; Some macOS machines run llvm when you type gcc.  (!)
+    ;; We can't even check if it's a symlink; it's a binary placed in
+    ;; "/usr/bin/gcc".  So check the output and just skip this test if
+    ;; it says "Apple LLVM".
+    (unless (string-match "Apple LLVM" (car semantic-gcc-test-strings))
+        (semantic-gcc-test-output-parser))))
 
 ;;; gcc-tests.el ends here



reply via email to

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